boris-behav-obs 9.6.1__tar.gz → 9.6.3__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.
Files changed (129) hide show
  1. {boris_behav_obs-9.6.1/boris_behav_obs.egg-info → boris_behav_obs-9.6.3}/PKG-INFO +12 -8
  2. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/README.md +9 -6
  3. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/add_modifier.py +1 -5
  4. boris_behav_obs-9.6.3/boris/analysis_plugins/irr_cohen_kappa.py +72 -0
  5. boris_behav_obs-9.6.3/boris/analysis_plugins/irr_cohen_kappa_with_modifiers.py +77 -0
  6. boris_behav_obs-9.6.3/boris/analysis_plugins/irr_weighted_cohen_kappa.py +120 -0
  7. boris_behav_obs-9.6.3/boris/analysis_plugins/irr_weighted_cohen_kappa_with_modifiers.py +125 -0
  8. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/analysis_plugins/time_budget.py +0 -4
  9. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/behav_coding_map_creator.py +0 -1
  10. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/boris_cli.py +1 -1
  11. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/coding_pad.py +0 -2
  12. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/core.py +11 -28
  13. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/core_qrc.py +3 -0
  14. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/db_functions.py +4 -4
  15. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/edit_event.py +0 -9
  16. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/exclusion_matrix.py +1 -1
  17. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/export_events.py +63 -71
  18. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/gui_utilities.py +0 -1
  19. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/irr.py +10 -22
  20. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/menu_options.py +2 -0
  21. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/modifier_coding_map_creator.py +0 -2
  22. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/observation_operations.py +2 -4
  23. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/param_panel.py +0 -4
  24. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/plot_spectrogram_rt.py +2 -1
  25. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/plot_waveform_rt.py +2 -1
  26. boris_behav_obs-9.6.3/boris/portion/__init__.py +31 -0
  27. boris_behav_obs-9.6.3/boris/portion/const.py +95 -0
  28. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/portion/dict.py +5 -5
  29. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/portion/func.py +2 -2
  30. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/portion/interval.py +21 -41
  31. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/portion/io.py +41 -32
  32. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/project_functions.py +2 -1
  33. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/state_events.py +1 -1
  34. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/time_budget_functions.py +0 -9
  35. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/transitions.py +1 -1
  36. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/version.py +2 -2
  37. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/video_equalizer.py +0 -2
  38. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/view_df.py +0 -2
  39. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/write_event.py +4 -13
  40. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3/boris_behav_obs.egg-info}/PKG-INFO +12 -8
  41. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris_behav_obs.egg-info/SOURCES.txt +4 -0
  42. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris_behav_obs.egg-info/requires.txt +2 -1
  43. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/pyproject.toml +4 -3
  44. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/tests/test_db_functions.py +1 -6
  45. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/tests/test_export_observation.py +3 -21
  46. boris_behav_obs-9.6.3/tests/test_irr.py +300 -0
  47. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/tests/test_observation_gui.py +29 -27
  48. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/tests/test_otx_parser.py +6 -7
  49. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/tests/test_preferences_gui.py +8 -12
  50. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/tests/test_project_functions.py +37 -54
  51. boris_behav_obs-9.6.1/boris/portion/__init__.py +0 -21
  52. boris_behav_obs-9.6.1/boris/portion/const.py +0 -78
  53. boris_behav_obs-9.6.1/tests/test_irr.py +0 -342
  54. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/LICENSE.TXT +0 -0
  55. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/MANIFEST.in +0 -0
  56. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/README.TXT +0 -0
  57. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/__init__.py +0 -0
  58. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/__main__.py +0 -0
  59. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/about.py +0 -0
  60. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/add_modifier_ui.py +0 -0
  61. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/advanced_event_filtering.py +0 -0
  62. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/analysis_plugins/__init__.py +0 -0
  63. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/analysis_plugins/_latency.py +0 -0
  64. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/analysis_plugins/list_of_dataframe_columns.py +0 -0
  65. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/analysis_plugins/number_of_occurences.py +0 -0
  66. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/analysis_plugins/number_of_occurences_by_independent_variable.py +0 -0
  67. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/behavior_binary_table.py +0 -0
  68. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/behaviors_coding_map.py +0 -0
  69. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/cmd_arguments.py +0 -0
  70. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/config.py +0 -0
  71. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/config_file.py +0 -0
  72. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/connections.py +0 -0
  73. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/converters.py +0 -0
  74. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/converters_ui.py +0 -0
  75. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/cooccurence.py +0 -0
  76. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/core_ui.py +0 -0
  77. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/dev.py +0 -0
  78. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/dialog.py +0 -0
  79. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/duration_widget.py +0 -0
  80. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/edit_event_ui.py +0 -0
  81. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/event_operations.py +0 -0
  82. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/events_cursor.py +0 -0
  83. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/events_snapshots.py +0 -0
  84. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/export_observation.py +0 -0
  85. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/external_processes.py +0 -0
  86. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/geometric_measurement.py +0 -0
  87. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/image_overlay.py +0 -0
  88. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/import_observations.py +0 -0
  89. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/latency.py +0 -0
  90. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/measurement_widget.py +0 -0
  91. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/media_file.py +0 -0
  92. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/modifiers_coding_map.py +0 -0
  93. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/mpv-1.0.3.py +0 -0
  94. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/mpv.py +0 -0
  95. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/mpv2.py +0 -0
  96. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/observation.py +0 -0
  97. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/observation_ui.py +0 -0
  98. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/observations_list.py +0 -0
  99. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/otx_parser.py +0 -0
  100. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/param_panel_ui.py +0 -0
  101. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/player_dock_widget.py +0 -0
  102. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/plot_data_module.py +0 -0
  103. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/plot_events.py +0 -0
  104. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/plot_events_rt.py +0 -0
  105. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/plugins.py +0 -0
  106. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/preferences.py +0 -0
  107. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/preferences_ui.py +0 -0
  108. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/project.py +0 -0
  109. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/project_import_export.py +0 -0
  110. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/project_ui.py +0 -0
  111. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/qrc_boris.py +0 -0
  112. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/qrc_boris5.py +0 -0
  113. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/select_modifiers.py +0 -0
  114. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/select_observations.py +0 -0
  115. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/select_subj_behav.py +0 -0
  116. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/subjects_pad.py +0 -0
  117. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/synthetic_time_budget.py +0 -0
  118. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/time_budget_widget.py +0 -0
  119. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/utilities.py +0 -0
  120. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/video_equalizer_ui.py +0 -0
  121. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/video_operations.py +0 -0
  122. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris/view_df_ui.py +0 -0
  123. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris_behav_obs.egg-info/dependency_links.txt +0 -0
  124. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris_behav_obs.egg-info/entry_points.txt +0 -0
  125. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/boris_behav_obs.egg-info/top_level.txt +0 -0
  126. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/setup.cfg +0 -0
  127. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/tests/test_time_budget.py +0 -0
  128. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/tests/test_utilities.py +0 -0
  129. {boris_behav_obs-9.6.1 → boris_behav_obs-9.6.3}/tests/test_utilities2.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boris-behav-obs
3
- Version: 9.6.1
3
+ Version: 9.6.3
4
4
  Summary: BORIS - Behavioral Observation Research Interactive Software
5
5
  Author-email: Olivier Friard <olivier.friard@unito.it>
6
6
  License-Expression: GPL-3.0-only
@@ -19,7 +19,7 @@ Requires-Python: >=3.12
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE.TXT
21
21
  Requires-Dist: exifread>=3.0.0
22
- Requires-Dist: numpy>=1.26.4
22
+ Requires-Dist: numpy==2.3.2
23
23
  Requires-Dist: matplotlib>=3.3.3
24
24
  Requires-Dist: pandas>=2.2.2
25
25
  Requires-Dist: tablib[cli,html,ods,pandas,xls,xlsx]>=3
@@ -27,6 +27,7 @@ Requires-Dist: pyreadr
27
27
  Requires-Dist: pyside6==6.9
28
28
  Requires-Dist: hachoir>=3.3.0
29
29
  Requires-Dist: scipy>=1.15.3
30
+ Requires-Dist: scikit-learn>=1.7.1
30
31
  Provides-Extra: dev
31
32
  Requires-Dist: ruff; extra == "dev"
32
33
  Requires-Dist: pytest; extra == "dev"
@@ -48,7 +49,7 @@ You can not longer run BORIS natively on MacOS (since v.8). Some alternatives to
48
49
 
49
50
  It provides also some analysis tools like time budget and some plotting functions.
50
51
 
51
- The BORIS paper has more than [![BORIS citations counter](http://penelope.unito.it/friard/boris_scopus_citations.png) citations](https://www.boris.unito.it/citations) in peer-reviewed scientific publications.
52
+ The BORIS paper has more than [![BORIS citations counter](https://penelope.unito.it/friard/boris_scopus_citations.png) citations](https://www.boris.unito.it/citations) in peer-reviewed scientific publications.
52
53
 
53
54
 
54
55
 
@@ -58,13 +59,17 @@ See the official [BORIS web site](https://www.boris.unito.it).
58
59
  [![Python web site](https://img.shields.io/badge/Made%20with-Python-1f425f.svg)](https://www.python.org)
59
60
  ![Python versions](https://img.shields.io/pypi/pyversions/boris-behav-obs)
60
61
  ![BORIS license](https://img.shields.io/pypi/l/boris-behav-obs)
62
+ [![PyPI version](https://img.shields.io/pypi/v/boris-behav-obs.svg)](https://pypi.org/project/boris-behav-obs/)
63
+
61
64
  [![Number of downloads](https://static.pepy.tech/personalized-badge/boris-behav-obs?period=total&units=international_system&left_color=black&right_color=orange&left_text=Downloads)](https://pepy.tech/project/boris-behav-obs)
62
65
  ![commit-activity](https://img.shields.io/github/commit-activity/m/olivierfriard/BORIS)
63
- [![PyPI version](https://img.shields.io/pypi/v/boris-behav-obs.svg)](https://pypi.org/project/boris-behav-obs/)
64
- ![BORIS scopus citations badge](http://penelope.unito.it/friard/boris_scopus_citations.svg)
66
+ ![GitHub last commit](https://img.shields.io/github/last-commit/olivierfriard/BORIS)
65
67
 
68
+ ![BORIS scopus citations badge](https://penelope.unito.it/friard/boris_scopus_citations.svg)
66
69
 
67
70
 
71
+ ![GitHub Repo stars](https://img.shields.io/github/stars/olivierfriard/BORIS?style=flat&label=Stars)
72
+ [![Please Star](https://img.shields.io/badge/⭐-Star%20this%20repo-blue?style=flat-square)](https://github.com/olivierfriard/BORIS/stargazers)
68
73
 
69
74
  # Documentation
70
75
 
@@ -81,8 +86,7 @@ Some [video tutorials](https://www.boris.unito.it/video_tutorials/) are availabl
81
86
  # Bug reports and feature requests
82
87
 
83
88
 
84
- To search for bugs, report them or request a feature, please use the github tracker:
85
- https://github.com/olivierfriard/BORIS/issues
89
+ To search for bugs, report them or request a feature, please use the [GitHub issues tracker](https://github.com/olivierfriard/BORIS/issues)
86
90
 
87
91
 
88
92
 
@@ -128,7 +132,7 @@ GNU General Public License for more details.
128
132
 
129
133
  Distributed with a [GPL v.3 license](LICENSE.TXT).
130
134
 
131
- Copyright (C) 2012-2024 Olivier Friard
135
+ Copyright (C) 2012-2025 Olivier Friard
132
136
 
133
137
 
134
138
 
@@ -11,7 +11,7 @@ You can not longer run BORIS natively on MacOS (since v.8). Some alternatives to
11
11
 
12
12
  It provides also some analysis tools like time budget and some plotting functions.
13
13
 
14
- The BORIS paper has more than [![BORIS citations counter](http://penelope.unito.it/friard/boris_scopus_citations.png) citations](https://www.boris.unito.it/citations) in peer-reviewed scientific publications.
14
+ The BORIS paper has more than [![BORIS citations counter](https://penelope.unito.it/friard/boris_scopus_citations.png) citations](https://www.boris.unito.it/citations) in peer-reviewed scientific publications.
15
15
 
16
16
 
17
17
 
@@ -21,13 +21,17 @@ See the official [BORIS web site](https://www.boris.unito.it).
21
21
  [![Python web site](https://img.shields.io/badge/Made%20with-Python-1f425f.svg)](https://www.python.org)
22
22
  ![Python versions](https://img.shields.io/pypi/pyversions/boris-behav-obs)
23
23
  ![BORIS license](https://img.shields.io/pypi/l/boris-behav-obs)
24
+ [![PyPI version](https://img.shields.io/pypi/v/boris-behav-obs.svg)](https://pypi.org/project/boris-behav-obs/)
25
+
24
26
  [![Number of downloads](https://static.pepy.tech/personalized-badge/boris-behav-obs?period=total&units=international_system&left_color=black&right_color=orange&left_text=Downloads)](https://pepy.tech/project/boris-behav-obs)
25
27
  ![commit-activity](https://img.shields.io/github/commit-activity/m/olivierfriard/BORIS)
26
- [![PyPI version](https://img.shields.io/pypi/v/boris-behav-obs.svg)](https://pypi.org/project/boris-behav-obs/)
27
- ![BORIS scopus citations badge](http://penelope.unito.it/friard/boris_scopus_citations.svg)
28
+ ![GitHub last commit](https://img.shields.io/github/last-commit/olivierfriard/BORIS)
28
29
 
30
+ ![BORIS scopus citations badge](https://penelope.unito.it/friard/boris_scopus_citations.svg)
29
31
 
30
32
 
33
+ ![GitHub Repo stars](https://img.shields.io/github/stars/olivierfriard/BORIS?style=flat&label=Stars)
34
+ [![Please Star](https://img.shields.io/badge/⭐-Star%20this%20repo-blue?style=flat-square)](https://github.com/olivierfriard/BORIS/stargazers)
31
35
 
32
36
  # Documentation
33
37
 
@@ -44,8 +48,7 @@ Some [video tutorials](https://www.boris.unito.it/video_tutorials/) are availabl
44
48
  # Bug reports and feature requests
45
49
 
46
50
 
47
- To search for bugs, report them or request a feature, please use the github tracker:
48
- https://github.com/olivierfriard/BORIS/issues
51
+ To search for bugs, report them or request a feature, please use the [GitHub issues tracker](https://github.com/olivierfriard/BORIS/issues)
49
52
 
50
53
 
51
54
 
@@ -91,7 +94,7 @@ GNU General Public License for more details.
91
94
 
92
95
  Distributed with a [GPL v.3 license](LICENSE.TXT).
93
96
 
94
- Copyright (C) 2012-2024 Olivier Friard
97
+ Copyright (C) 2012-2025 Olivier Friard
95
98
 
96
99
 
97
100
 
@@ -123,11 +123,7 @@ class addModifierDialog(QDialog, Ui_Dialog):
123
123
  if (
124
124
  dialog.MessageDialog(
125
125
  cfg.programName,
126
- (
127
- "You are working on a behavior.<br>"
128
- "If you close the window it will be lost.<br>"
129
- "Do you want to change modifiers set"
130
- ),
126
+ ("You are working on a behavior.<br>If you close the window it will be lost.<br>Do you want to change modifiers set"),
131
127
  [cfg.CLOSE, cfg.CANCEL],
132
128
  )
133
129
  == cfg.CANCEL
@@ -0,0 +1,72 @@
1
+ """
2
+ BORIS plugin
3
+
4
+ Inter Rater Reliability (IRR) Unweighted Cohen Kappa
5
+ """
6
+
7
+ import pandas as pd
8
+ from sklearn.metrics import cohen_kappa_score
9
+
10
+ __version__ = "0.0.1"
11
+ __version_date__ = "2025-08-25"
12
+ __plugin_name__ = "Inter Rater Reliability - Unweighted Cohen Kappa"
13
+ __author__ = "Olivier Friard - University of Torino - Italy"
14
+
15
+
16
+ def run(df: pd.DataFrame):
17
+ """
18
+ Calculate the Inter Rater Reliability - Unweighted Cohen Kappa
19
+ """
20
+
21
+ # attribute a code for each interval
22
+ def get_code(t_start, obs):
23
+ for seg in obs:
24
+ if t_start >= seg[0] and t_start < seg[1]:
25
+ return seg[2]
26
+ return ""
27
+
28
+ # Get unique values as a numpy array
29
+ unique_obs = df["Observation id"].unique()
30
+
31
+ # Convert to a list
32
+ unique_obs_list = unique_obs.tolist()
33
+
34
+ # Convert to tuples grouped by observation
35
+ grouped = {
36
+ obs: [
37
+ (row[0], row[1], row[2] + "|" + row[3]) # concatenate subject and behavior with |
38
+ for row in group[["Start (s)", "Stop (s)", "Subject", "Behavior"]].itertuples(index=False, name=None)
39
+ ]
40
+ for obs, group in df.groupby("Observation id")
41
+ }
42
+
43
+ ck_results: dict = {}
44
+ for idx1, obs_id1 in enumerate(unique_obs_list):
45
+ obs1 = grouped[obs_id1]
46
+
47
+ ck_results[(obs_id1, obs_id1)] = "1.000"
48
+
49
+ for obs_id2 in unique_obs_list[idx1 + 1 :]:
50
+ obs2 = grouped[obs_id2]
51
+
52
+ # get all the break points
53
+ time_points = sorted(set([t for seg in obs1 for t in seg[:2]] + [t for seg in obs2 for t in seg[:2]]))
54
+
55
+ # elementary intervals
56
+ elementary_intervals = [(time_points[i], time_points[i + 1]) for i in range(len(time_points) - 1)]
57
+
58
+ obs1_codes = [get_code(t[0], obs1) for t in elementary_intervals]
59
+
60
+ obs2_codes = [get_code(t[0], obs2) for t in elementary_intervals]
61
+
62
+ # Cohen's Kappa
63
+ kappa = cohen_kappa_score(obs1_codes, obs2_codes)
64
+ print(f"{obs_id1} - {obs_id2}: Cohen's Kappa : {kappa:.3f}")
65
+
66
+ ck_results[(obs_id1, obs_id2)] = f"{kappa:.3f}"
67
+ ck_results[(obs_id2, obs_id1)] = f"{kappa:.3f}"
68
+
69
+ # DataFrame conversion
70
+ df_results = pd.Series(ck_results).unstack()
71
+
72
+ return df_results
@@ -0,0 +1,77 @@
1
+ """
2
+ BORIS plugin
3
+
4
+ Inter Rater Reliability (IRR) Unweighted Cohen Kappa with modifiers
5
+ """
6
+
7
+ import pandas as pd
8
+ from sklearn.metrics import cohen_kappa_score
9
+
10
+ __version__ = "0.0.1"
11
+ __version_date__ = "2025-08-25"
12
+ __plugin_name__ = "Inter Rater Reliability - Unweighted Cohen Kappa with modifiers"
13
+ __author__ = "Olivier Friard - University of Torino - Italy"
14
+
15
+
16
+ def run(df: pd.DataFrame):
17
+ """
18
+ Calculate the Inter Rater Reliability - Unweighted Cohen Kappa with modifiers
19
+ """
20
+
21
+ # attribute a code for each interval
22
+ def get_code(t_start, obs):
23
+ for seg in obs:
24
+ if t_start >= seg[0] and t_start < seg[1]:
25
+ return seg[2]
26
+ return ""
27
+
28
+ # Get unique values as a numpy array
29
+ unique_obs = df["Observation id"].unique()
30
+
31
+ # Convert to a list
32
+ unique_obs_list = unique_obs.tolist()
33
+
34
+ # Convert to tuples grouped by observation
35
+ grouped: dict = {}
36
+ modifiers: list = []
37
+ for col in df.columns:
38
+ if isinstance(col, tuple):
39
+ modifiers.append(col)
40
+
41
+ for obs, group in df.groupby("Observation id"):
42
+ o: list = []
43
+ for row in group[["Start (s)", "Stop (s)", "Subject", "Behavior"] + modifiers].itertuples(index=False, name=None):
44
+ modif_list = [row[i] for idx, i in enumerate(range(4, 4 + len(modifiers))) if modifiers[idx][0] == row[3]]
45
+ o.append((row[0], row[1], row[2] + "|" + row[3] + "|" + ",".join(modif_list)))
46
+ grouped[obs] = o
47
+
48
+ ck_results: dict = {}
49
+ for idx1, obs_id1 in enumerate(unique_obs_list):
50
+ obs1 = grouped[obs_id1]
51
+
52
+ ck_results[(obs_id1, obs_id1)] = "1.000"
53
+
54
+ for obs_id2 in unique_obs_list[idx1 + 1 :]:
55
+ obs2 = grouped[obs_id2]
56
+
57
+ # get all the break points
58
+ time_points = sorted(set([t for seg in obs1 for t in seg[:2]] + [t for seg in obs2 for t in seg[:2]]))
59
+
60
+ # elementary intervals
61
+ elementary_intervals = [(time_points[i], time_points[i + 1]) for i in range(len(time_points) - 1)]
62
+
63
+ obs1_codes = [get_code(t[0], obs1) for t in elementary_intervals]
64
+
65
+ obs2_codes = [get_code(t[0], obs2) for t in elementary_intervals]
66
+
67
+ # Cohen's Kappa
68
+ kappa = cohen_kappa_score(obs1_codes, obs2_codes)
69
+ print(f"{obs_id1} - {obs_id2}: Cohen's Kappa : {kappa:.3f}")
70
+
71
+ ck_results[(obs_id1, obs_id2)] = f"{kappa:.3f}"
72
+ ck_results[(obs_id2, obs_id1)] = f"{kappa:.3f}"
73
+
74
+ # DataFrame conversion
75
+ df_results = pd.Series(ck_results).unstack()
76
+
77
+ return df_results
@@ -0,0 +1,120 @@
1
+ """
2
+ BORIS plugin
3
+
4
+ Inter Rater Reliability (IRR) Weighted Cohen Kappa
5
+ """
6
+
7
+ import pandas as pd
8
+ from typing import List, Tuple, Dict, Optional
9
+
10
+ __version__ = "0.0.1"
11
+ __version_date__ = "2025-08-25"
12
+ __plugin_name__ = "Inter Rater Reliability - Weighted Cohen Kappa"
13
+ __author__ = "Olivier Friard - University of Torino - Italy"
14
+
15
+
16
+ def run(df: pd.DataFrame):
17
+ """
18
+ Calculate the Inter Rater Reliability - Weighted Cohen Kappa
19
+ """
20
+
21
+ def cohen_kappa_weighted_by_time(
22
+ obs1: List[Tuple[float, float, str]], obs2: List[Tuple[float, float, str]]
23
+ ) -> Tuple[float, float, float, Dict[Tuple[Optional[str], Optional[str]], float]]:
24
+ """
25
+ Compute Cohen's Kappa weighted by time duration.
26
+
27
+ Args:
28
+ obs1: List of (start_time, end_time, code) for observer 1
29
+ obs2: List of (start_time, end_time, code) for observer 2
30
+
31
+ Returns:
32
+ kappa (float): Cohen's Kappa weighted by duration
33
+ po (float): Observed agreement proportion (weighted)
34
+ pe (float): Expected agreement proportion by chance (weighted)
35
+ contingency (dict): Contingency table {(code1, code2): total_duration}
36
+ """
37
+
38
+ # 1. Collect all time boundaries from both observers
39
+ time_points = sorted(set([t for seg in obs1 for t in seg[:2]] + [t for seg in obs2 for t in seg[:2]]))
40
+
41
+ # 2. Build elementary intervals (non-overlapping time bins)
42
+ elementary_intervals = [(time_points[i], time_points[i + 1]) for i in range(len(time_points) - 1)]
43
+
44
+ # 3. Helper: get the active code for an observer at a given time
45
+ def get_code(t: float, obs: List[Tuple[float, float, str]]) -> Optional[str]:
46
+ for seg in obs:
47
+ if seg[0] <= t < seg[1]:
48
+ return seg[2]
49
+ return None # in case no segment covers this time
50
+
51
+ # 4. Build weighted contingency table (durations instead of counts)
52
+ contingency: Dict[Tuple[Optional[str], Optional[str]], float] = {}
53
+ total_time = 0.0
54
+
55
+ for start, end in elementary_intervals:
56
+ c1 = get_code(start, obs1)
57
+ c2 = get_code(start, obs2)
58
+ duration = end - start
59
+ total_time += duration
60
+ contingency[(c1, c2)] = contingency.get((c1, c2), 0.0) + duration
61
+
62
+ # 5. Observed agreement (po)
63
+ po = sum(duration for (c1, c2), duration in contingency.items() if c1 == c2) / total_time
64
+
65
+ # Marginal distributions for each observer
66
+ codes1: Dict[Optional[str], float] = {}
67
+ codes2: Dict[Optional[str], float] = {}
68
+ for (c1, c2), duration in contingency.items():
69
+ codes1[c1] = codes1.get(c1, 0.0) + duration
70
+ codes2[c2] = codes2.get(c2, 0.0) + duration
71
+
72
+ # 6. Expected agreement (pe), using marginal proportions
73
+ all_codes = set(codes1) | set(codes2)
74
+ pe = sum((codes1.get(c, 0.0) / total_time) * (codes2.get(c, 0.0) / total_time) for c in all_codes)
75
+
76
+ # 7. Kappa calculation
77
+ kappa = (po - pe) / (1 - pe) if (1 - pe) != 0 else 0.0
78
+
79
+ return kappa, po, pe, contingency
80
+
81
+ # Get unique values as a numpy array
82
+ unique_obs = df["Observation id"].unique()
83
+
84
+ # Convert to a list
85
+ unique_obs_list = unique_obs.tolist()
86
+
87
+ # Convert to tuples grouped by observation
88
+ grouped = {
89
+ obs: [
90
+ (row[0], row[1], row[2] + "|" + row[3]) # concatenate subject and behavior with |
91
+ for row in group[["Start (s)", "Stop (s)", "Subject", "Behavior"]].itertuples(index=False, name=None)
92
+ ]
93
+ for obs, group in df.groupby("Observation id")
94
+ }
95
+
96
+ ck_results: dict = {}
97
+ str_results: str = ""
98
+ for idx1, obs_id1 in enumerate(unique_obs_list):
99
+ obs1 = grouped[obs_id1]
100
+
101
+ ck_results[(obs_id1, obs_id1)] = "1.000"
102
+
103
+ for obs_id2 in unique_obs_list[idx1 + 1 :]:
104
+ obs2 = grouped[obs_id2]
105
+
106
+ # Cohen's Kappa
107
+ kappa, po, pe, table = cohen_kappa_weighted_by_time(obs1, obs2)
108
+
109
+ print(f"{obs_id1} - {obs_id2}: Cohen's Kappa: {kappa:.3f} Expected agreement: {pe:.3f} Observed agreement: {po:.3f}")
110
+ str_results += (
111
+ f"{obs_id1} - {obs_id2}: Cohen's Kappa: {kappa:.3f} Expected agreement: {pe:.3f} Observed agreement: {po:.3f}\n"
112
+ )
113
+
114
+ ck_results[(obs_id1, obs_id2)] = f"{kappa:.3f}"
115
+ ck_results[(obs_id2, obs_id1)] = f"{kappa:.3f}"
116
+
117
+ # DataFrame conversion
118
+ df_results = pd.Series(ck_results).unstack()
119
+
120
+ return df_results, str_results
@@ -0,0 +1,125 @@
1
+ """
2
+ BORIS plugin
3
+
4
+ Inter Rater Reliability (IRR) Weighted Cohen Kappa with modifiers
5
+ """
6
+
7
+ import pandas as pd
8
+ from typing import List, Tuple, Dict, Optional
9
+
10
+ __version__ = "0.0.1"
11
+ __version_date__ = "2025-08-25"
12
+ __plugin_name__ = "Inter Rater Reliability - Weighted Cohen Kappa with modifiers"
13
+ __author__ = "Olivier Friard - University of Torino - Italy"
14
+
15
+
16
+ def run(df: pd.DataFrame):
17
+ """
18
+ Calculate the Inter Rater Reliability - Weighted Cohen Kappa with modifiers
19
+ """
20
+
21
+ def cohen_kappa_weighted_by_time(
22
+ obs1: List[Tuple[float, float, str]], obs2: List[Tuple[float, float, str]]
23
+ ) -> Tuple[float, float, float, Dict[Tuple[Optional[str], Optional[str]], float]]:
24
+ """
25
+ Compute Cohen's Kappa weighted by time duration with modifiers.
26
+
27
+ Args:
28
+ obs1: List of (start_time, end_time, code) for observer 1
29
+ obs2: List of (start_time, end_time, code) for observer 2
30
+
31
+ Returns:
32
+ kappa (float): Cohen's Kappa weighted by duration
33
+ po (float): Observed agreement proportion (weighted)
34
+ pe (float): Expected agreement proportion by chance (weighted)
35
+ contingency (dict): Contingency table {(code1, code2): total_duration}
36
+ """
37
+
38
+ # 1. Collect all time boundaries from both observers
39
+ time_points = sorted(set([t for seg in obs1 for t in seg[:2]] + [t for seg in obs2 for t in seg[:2]]))
40
+
41
+ # 2. Build elementary intervals (non-overlapping time bins)
42
+ elementary_intervals = [(time_points[i], time_points[i + 1]) for i in range(len(time_points) - 1)]
43
+
44
+ # 3. Helper: get the active code for an observer at a given time
45
+ def get_code(t: float, obs: List[Tuple[float, float, str]]) -> Optional[str]:
46
+ for seg in obs:
47
+ if seg[0] <= t < seg[1]:
48
+ return seg[2]
49
+ return None # in case no segment covers this time
50
+
51
+ # 4. Build weighted contingency table (durations instead of counts)
52
+ contingency: Dict[Tuple[Optional[str], Optional[str]], float] = {}
53
+ total_time = 0.0
54
+
55
+ for start, end in elementary_intervals:
56
+ c1 = get_code(start, obs1)
57
+ c2 = get_code(start, obs2)
58
+ duration = end - start
59
+ total_time += duration
60
+ contingency[(c1, c2)] = contingency.get((c1, c2), 0.0) + duration
61
+
62
+ # 5. Observed agreement (po)
63
+ po = sum(duration for (c1, c2), duration in contingency.items() if c1 == c2) / total_time
64
+
65
+ # Marginal distributions for each observer
66
+ codes1: Dict[Optional[str], float] = {}
67
+ codes2: Dict[Optional[str], float] = {}
68
+ for (c1, c2), duration in contingency.items():
69
+ codes1[c1] = codes1.get(c1, 0.0) + duration
70
+ codes2[c2] = codes2.get(c2, 0.0) + duration
71
+
72
+ # 6. Expected agreement (pe), using marginal proportions
73
+ all_codes = set(codes1) | set(codes2)
74
+ pe = sum((codes1.get(c, 0.0) / total_time) * (codes2.get(c, 0.0) / total_time) for c in all_codes)
75
+
76
+ # 7. Kappa calculation
77
+ kappa = (po - pe) / (1 - pe) if (1 - pe) != 0 else 0.0
78
+
79
+ return kappa, po, pe, contingency
80
+
81
+ # Get unique values as a numpy array
82
+ unique_obs = df["Observation id"].unique()
83
+
84
+ # Convert to a list
85
+ unique_obs_list = unique_obs.tolist()
86
+
87
+ # Convert to tuples grouped by observation
88
+ grouped: dict = {}
89
+ modifiers: list = []
90
+ for col in df.columns:
91
+ if isinstance(col, tuple):
92
+ modifiers.append(col)
93
+
94
+ for obs, group in df.groupby("Observation id"):
95
+ o = []
96
+ for row in group[["Start (s)", "Stop (s)", "Subject", "Behavior"] + modifiers].itertuples(index=False, name=None):
97
+ modif_list = [row[i] for idx, i in enumerate(range(4, 4 + len(modifiers))) if modifiers[idx][0] == row[3]]
98
+ o.append((row[0], row[1], row[2] + "|" + row[3] + "|" + ",".join(modif_list)))
99
+ grouped[obs] = o
100
+
101
+ ck_results: dict = {}
102
+ str_results: str = ""
103
+ for idx1, obs_id1 in enumerate(unique_obs_list):
104
+ obs1 = grouped[obs_id1]
105
+
106
+ ck_results[(obs_id1, obs_id1)] = "1.000"
107
+
108
+ for obs_id2 in unique_obs_list[idx1 + 1 :]:
109
+ obs2 = grouped[obs_id2]
110
+
111
+ # Cohen's Kappa
112
+ kappa, po, pe, table = cohen_kappa_weighted_by_time(obs1, obs2)
113
+
114
+ print(f"{obs_id1} - {obs_id2}: Cohen's Kappa: {kappa:.3f} Expected agreement: {pe:.3f} Observed agreement: {po:.3f}")
115
+ str_results += (
116
+ f"{obs_id1} - {obs_id2}: Cohen's Kappa: {kappa:.3f} Expected agreement: {pe:.3f} Observed agreement: {po:.3f}\n"
117
+ )
118
+
119
+ ck_results[(obs_id1, obs_id2)] = f"{kappa:.3f}"
120
+ ck_results[(obs_id2, obs_id1)] = f"{kappa:.3f}"
121
+
122
+ # DataFrame conversion
123
+ df_results = pd.Series(ck_results).unstack()
124
+
125
+ return df_results, str_results
@@ -26,10 +26,6 @@ def run(df: pd.DataFrame):
26
26
  - % of total subject observation duration
27
27
  """
28
28
 
29
- print("running time budget plugin")
30
-
31
- print(df)
32
-
33
29
  group_by = ["Subject", "Behavior"]
34
30
 
35
31
  dfs = [
@@ -431,7 +431,6 @@ class BehaviorsMapCreatorWindow(QMainWindow):
431
431
  self.selectedPolygon = None
432
432
  self.selectedPolygonMemBrush = None
433
433
 
434
- print(self.polygonsList2)
435
434
  idx = 0
436
435
  for areaCode, pg in self.polygonsList2:
437
436
  if pg.contains(test):
@@ -252,7 +252,7 @@ if args.command:
252
252
 
253
253
  K, out = irr.cohen_kappa(cursor, observations_id_list[0], observations_id_list[1], interval, subjects, include_modifiers)
254
254
 
255
- print(("Cohen's Kappa - Index of Inter-Rater Reliability\n\n" "Interval time: {interval:.3f} s\n").format(interval=interval))
255
+ print(("Cohen's Kappa - Index of Inter-Rater Reliability\n\nInterval time: {interval:.3f} s\n").format(interval=interval))
256
256
 
257
257
  print(out)
258
258
  sys.exit()
@@ -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()