zarafe 1.0.1__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 (71) hide show
  1. zarafe-1.0.1/.claude/settings.local.json +8 -0
  2. zarafe-1.0.1/.gitignore +176 -0
  3. zarafe-1.0.1/CLAUDE.md +36 -0
  4. zarafe-1.0.1/LICENSE +21 -0
  5. zarafe-1.0.1/PKG-INFO +127 -0
  6. zarafe-1.0.1/README.md +88 -0
  7. zarafe-1.0.1/build-tools/__init__.py +1 -0
  8. zarafe-1.0.1/build-tools/pyinstaller-hooks/README.md +34 -0
  9. zarafe-1.0.1/build-tools/pyinstaller-hooks/__init__.py +1 -0
  10. zarafe-1.0.1/build-tools/pyinstaller-hooks/hook-ffmpeg.py +12 -0
  11. zarafe-1.0.1/build-tools/pyinstaller-hooks/pyi_rth_ffmpeg.py +60 -0
  12. zarafe-1.0.1/main.py +41 -0
  13. zarafe-1.0.1/pyproject.toml +149 -0
  14. zarafe-1.0.1/resources/Funded_by_EU_Eyes4ICU.png +0 -0
  15. zarafe-1.0.1/resources/app.png +0 -0
  16. zarafe-1.0.1/resources/app_icon.icns +0 -0
  17. zarafe-1.0.1/resources/app_icon.ico +0 -0
  18. zarafe-1.0.1/resources/giraffe.png +0 -0
  19. zarafe-1.0.1/resources/icons/add_circle.svg +1 -0
  20. zarafe-1.0.1/resources/icons/arrow_down.svg +1 -0
  21. zarafe-1.0.1/resources/icons/arrow_up.svg +1 -0
  22. zarafe-1.0.1/resources/icons/chevron_left.svg +1 -0
  23. zarafe-1.0.1/resources/icons/chevron_right.svg +1 -0
  24. zarafe-1.0.1/resources/icons/delete.svg +1 -0
  25. zarafe-1.0.1/resources/icons/edit.svg +1 -0
  26. zarafe-1.0.1/resources/icons/mark_end.svg +1 -0
  27. zarafe-1.0.1/resources/icons/mark_start.svg +1 -0
  28. zarafe-1.0.1/resources/icons/mute.svg +1 -0
  29. zarafe-1.0.1/resources/icons/pause.svg +1 -0
  30. zarafe-1.0.1/resources/icons/play.svg +1 -0
  31. zarafe-1.0.1/resources/icons/save.svg +1 -0
  32. zarafe-1.0.1/resources/icons/volume.svg +1 -0
  33. zarafe-1.0.1/resources/icons/warning.svg +1 -0
  34. zarafe-1.0.1/uv.lock +1835 -0
  35. zarafe-1.0.1/zarafe/__init__.py +3 -0
  36. zarafe-1.0.1/zarafe/controllers/__init__.py +1 -0
  37. zarafe-1.0.1/zarafe/controllers/main_controller.py +83 -0
  38. zarafe-1.0.1/zarafe/controllers/project_controller.py +123 -0
  39. zarafe-1.0.1/zarafe/controllers/video_navigation_controller.py +45 -0
  40. zarafe-1.0.1/zarafe/core/__init__.py +1 -0
  41. zarafe-1.0.1/zarafe/core/audio_manager.py +62 -0
  42. zarafe-1.0.1/zarafe/core/color_theme_manager.py +47 -0
  43. zarafe-1.0.1/zarafe/core/config.py +55 -0
  44. zarafe-1.0.1/zarafe/core/configuration_service.py +57 -0
  45. zarafe-1.0.1/zarafe/core/event_manager.py +252 -0
  46. zarafe-1.0.1/zarafe/core/event_type_registry.py +51 -0
  47. zarafe-1.0.1/zarafe/core/gaze_data.py +38 -0
  48. zarafe-1.0.1/zarafe/core/shortcut_manager.py +56 -0
  49. zarafe-1.0.1/zarafe/core/video_manager.py +121 -0
  50. zarafe-1.0.1/zarafe/main_window.py +453 -0
  51. zarafe-1.0.1/zarafe/utils/__init__.py +1 -0
  52. zarafe-1.0.1/zarafe/utils/ffmpeg_compat.py +55 -0
  53. zarafe-1.0.1/zarafe/utils/file_utils.py +26 -0
  54. zarafe-1.0.1/zarafe/utils/icon_loader.py +88 -0
  55. zarafe-1.0.1/zarafe/utils/importer.py +148 -0
  56. zarafe-1.0.1/zarafe/utils/sorting.py +19 -0
  57. zarafe-1.0.1/zarafe/utils/theme.py +186 -0
  58. zarafe-1.0.1/zarafe/widgets/__init__.py +1 -0
  59. zarafe-1.0.1/zarafe/widgets/about_dialog.py +62 -0
  60. zarafe-1.0.1/zarafe/widgets/base_dialog.py +213 -0
  61. zarafe-1.0.1/zarafe/widgets/event_controls.py +113 -0
  62. zarafe-1.0.1/zarafe/widgets/menu_manager.py +76 -0
  63. zarafe-1.0.1/zarafe/widgets/metadata_panel.py +22 -0
  64. zarafe-1.0.1/zarafe/widgets/new_project_dialog.py +721 -0
  65. zarafe-1.0.1/zarafe/widgets/panels/__init__.py +1 -0
  66. zarafe-1.0.1/zarafe/widgets/panels/left_panel.py +54 -0
  67. zarafe-1.0.1/zarafe/widgets/panels/main_layout_manager.py +76 -0
  68. zarafe-1.0.1/zarafe/widgets/project_dialog.py +291 -0
  69. zarafe-1.0.1/zarafe/widgets/pupil_plot.py +136 -0
  70. zarafe-1.0.1/zarafe/widgets/video_controls.py +84 -0
  71. zarafe-1.0.1/zarafe/widgets/video_display.py +189 -0
@@ -0,0 +1,8 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(git add:*)"
5
+ ],
6
+ "deny": []
7
+ }
8
+ }
@@ -0,0 +1,176 @@
1
+ .DS_Store
2
+
3
+ # Byte-compiled / optimized / DLL files
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+
8
+ # C extensions
9
+ *.so
10
+
11
+ # Distribution / packaging
12
+ .Python
13
+ build/
14
+ develop-eggs/
15
+ dist/
16
+ downloads/
17
+ eggs/
18
+ .eggs/
19
+ lib/
20
+ lib64/
21
+ parts/
22
+ sdist/
23
+ var/
24
+ wheels/
25
+ share/python-wheels/
26
+ *.egg-info/
27
+ .installed.cfg
28
+ *.egg
29
+ MANIFEST
30
+
31
+ # PyInstaller
32
+ # Usually these files are written by a python script from a template
33
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
34
+ *.manifest
35
+ *.spec
36
+
37
+ # Installer logs
38
+ pip-log.txt
39
+ pip-delete-this-directory.txt
40
+
41
+ # Unit test / coverage reports
42
+ htmlcov/
43
+ .tox/
44
+ .nox/
45
+ .coverage
46
+ .coverage.*
47
+ .cache
48
+ nosetests.xml
49
+ coverage.xml
50
+ *.cover
51
+ *.py,cover
52
+ .hypothesis/
53
+ .pytest_cache/
54
+ cover/
55
+
56
+ # Translations
57
+ *.mo
58
+ *.pot
59
+
60
+ # Django stuff:
61
+ *.log
62
+ local_settings.py
63
+ db.sqlite3
64
+ db.sqlite3-journal
65
+
66
+ # Flask stuff:
67
+ instance/
68
+ .webassets-cache
69
+
70
+ # Scrapy stuff:
71
+ .scrapy
72
+
73
+ # Sphinx documentation
74
+ docs/_build/
75
+
76
+ # PyBuilder
77
+ .pybuilder/
78
+ target/
79
+
80
+ # Jupyter Notebook
81
+ .ipynb_checkpoints
82
+
83
+ # IPython
84
+ profile_default/
85
+ ipython_config.py
86
+
87
+ # pyenv
88
+ # For a library or package, you might want to ignore these files since the code is
89
+ # intended to run in multiple environments; otherwise, check them in:
90
+ # .python-version
91
+
92
+ # pipenv
93
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
94
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
95
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
96
+ # install all needed dependencies.
97
+ #Pipfile.lock
98
+
99
+ # UV
100
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
101
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
102
+ # commonly ignored for libraries.
103
+ #uv.lock
104
+
105
+ # poetry
106
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
107
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
108
+ # commonly ignored for libraries.
109
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
110
+ #poetry.lock
111
+
112
+ # pdm
113
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
114
+ #pdm.lock
115
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
116
+ # in version control.
117
+ # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
118
+ .pdm.toml
119
+ .pdm-python
120
+ .pdm-build/
121
+
122
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
123
+ __pypackages__/
124
+
125
+ # Celery stuff
126
+ celerybeat-schedule
127
+ celerybeat.pid
128
+
129
+ # SageMath parsed files
130
+ *.sage.py
131
+
132
+ # Environments
133
+ .env
134
+ .venv
135
+ env/
136
+ venv/
137
+ ENV/
138
+ env.bak/
139
+ venv.bak/
140
+
141
+ # Spyder project settings
142
+ .spyderproject
143
+ .spyproject
144
+
145
+ # Rope project settings
146
+ .ropeproject
147
+
148
+ # mkdocs documentation
149
+ /site
150
+
151
+ # mypy
152
+ .mypy_cache/
153
+ .dmypy.json
154
+ dmypy.json
155
+
156
+ # Pyre type checker
157
+ .pyre/
158
+
159
+ # pytype static type analyzer
160
+ .pytype/
161
+
162
+ # Cython debug symbols
163
+ cython_debug/
164
+
165
+ # PyCharm
166
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
167
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
168
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
169
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
170
+ #.idea/
171
+
172
+ # PyPI configuration file
173
+ .pypirc
174
+
175
+ # Local release documentation (contains sensitive info)
176
+ PYPI_RELEASE.md
zarafe-1.0.1/CLAUDE.md ADDED
@@ -0,0 +1,36 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Git Commit Guidelines
6
+ - NEVER mention AI generation in git commit messages (no "Generated with AI", "AI-assisted", etc.)
7
+
8
+ ## Development Environment
9
+
10
+ - **Python Version**: Requires Python ≥3.9
11
+ - **Virtual Environment**: Uses uv for dependency management
12
+
13
+ ## Commit Message Style
14
+
15
+ Follow the conventional commit format used in this repository:
16
+ - **fix**: Bug fixes (e.g., "fix: handle invalid reflection geometry instead of crashing")
17
+ - **feature**: New features (e.g., "feature: calculate the 3D position of the fovea on the retinal surface")
18
+ - **enhance**: Improvements to existing functionality (e.g., "enhance: better plot")
19
+ - **refactor**: Code restructuring without changing functionality (e.g., "refactor: making the code more pythonic")
20
+ - **chore**: Maintenance tasks (e.g., "chore: better error message")
21
+ - **add**: Adding new components (e.g., "add: step by step angle kappa calculation")
22
+
23
+ Keep messages concise but descriptive. Focus on what the change accomplishes rather than how it was implemented.
24
+
25
+ ## Code Comments Guidelines
26
+
27
+ When writing code comments, follow the same principle as good commit messages - only write them when the code needs explanation. Only add comments when the logic is non-trivial, has business context, or needs explanation that isn't obvious from reading the code. Keep comments concise and only explain what actually needs explaining.
28
+ It's ok to have comments for block of the code so we know this section is for that and finding things becomes easear.
29
+
30
+ ## Python Import Guidelines
31
+
32
+ - **NEVER import modules in the middle of functions or code blocks**
33
+ - **ALL imports must be at the top level of the file** (after module docstring)
34
+ - Group imports in standard order: standard library, third-party packages, local modules
35
+ - Use absolute imports when possible
36
+ - Avoid importing inside functions unless absolutely necessary for lazy loading or circular imports
zarafe-1.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Mohammadhossein Salari
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
zarafe-1.0.1/PKG-INFO ADDED
@@ -0,0 +1,127 @@
1
+ Metadata-Version: 2.4
2
+ Name: zarafe
3
+ Version: 1.0.1
4
+ Summary: Video annotation tool for marking timed events in eye tracking research
5
+ Author-email: Mohammadhossein Salari <mohammadhossein.salari@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2024 Mohammadhossein Salari
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ License-File: LICENSE
28
+ Requires-Python: >=3.11
29
+ Requires-Dist: glassestools==1.23.1
30
+ Requires-Dist: numpy>=2.3.0
31
+ Requires-Dist: opencv-python-headless>=4.11.0
32
+ Requires-Dist: pandas>=2.3.0
33
+ Requires-Dist: pyqt6>=6.9.0
34
+ Requires-Dist: pyqtgraph>=0.13.7
35
+ Requires-Dist: scipy>=1.16.0
36
+ Provides-Extra: dev
37
+ Requires-Dist: pytest; extra == 'dev'
38
+ Description-Content-Type: text/markdown
39
+
40
+ # Zarafe <img src="resources/app_icon.ico" alt="zarafe" width="30" height="30">
41
+
42
+ Zarafe is a video annotation tool designed for marking time events in eye tracking videos with gaze data visualization.
43
+
44
+ <p align="center">
45
+ <img src="resources/app.png" alt="EyE Annotation Tool Main Page" width="800">
46
+ </p>
47
+
48
+ ## Overview
49
+
50
+ This tool allows users to:
51
+ - Load directories containing worldCamera.mp4 recordings and gazeData.tsv files
52
+ - View eye tracking videos with gaze position overlays
53
+ - Create, mark and manage time-based event annotations
54
+ - Save annotations to CSV files for further analysis
55
+
56
+ ## Data Preparation
57
+
58
+ **Important**: Before using Zarafe, you need to convert your eye tracking data:
59
+
60
+ Zarafe uses [glassesValidator](https://github.com/dcnieho/glassesValidator) to import your eye tracking data. Some eye trackers require preprocessing before importing:
61
+
62
+ - **Pupil Labs**: Export from Pupil/Neon Player (disable World Video Exporter) or Pupil Cloud
63
+ - **Meta Project Aria Gen 1**: Process in Aria Studio with MPS eye gaze run, then use provided export script
64
+ - **SMI ETG**: Export raw data and scene video from BeGaze with specific settings
65
+
66
+ For detailed preprocessing instructions for your specific eye tracker, see the [glassesValidator preprocessing guide](https://github.com/dcnieho/glassesValidator?tab=readme-ov-file#eye-trackers).
67
+
68
+ The import process will generate the required worldCamera.mp4 and gazeData.tsv files.
69
+
70
+ Zarafe expects a specific directory structure with each recording in its own folder containing both files.
71
+
72
+ ## Installation
73
+
74
+ 1. Clone this repository:
75
+ ```bash
76
+ git clone https://github.com/mh-salari/zarafe.git
77
+ cd zarafe
78
+ ```
79
+
80
+ 2. Install dependencies (choose one method):
81
+
82
+ **Option A: Using uv (recommended)**
83
+ ```bash
84
+ # Install uv from https://docs.astral.sh/uv/getting-started/installation/
85
+
86
+ # Install dependencies
87
+ uv sync
88
+ ```
89
+
90
+ **Option B: Using pip**
91
+ ```bash
92
+ pip install -e .
93
+ ```
94
+
95
+ 3. Run the application:
96
+ ```bash
97
+ # With uv
98
+ uv run python main.py
99
+
100
+ # With pip
101
+ python main.py
102
+ ```
103
+
104
+ ## Notes
105
+
106
+ Zarafe was developed by Mohammadhossein Salari with assistance from Claude 3.7 Sonnet, an AI assistant developed by Anthropic. Please be aware that this software is primarily for internal purposes and is not thoroughly documented.
107
+
108
+
109
+ ## License
110
+
111
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
112
+
113
+ ## Acknowledgments
114
+
115
+
116
+ Zarafe uses glassesValidator for data import. If you use this functionality, please cite:
117
+
118
+ Niehorster, D.C., Hessels, R.S., Benjamins, J.S., Nyström, M. and Hooge, I.T.C. (2023). GlassesValidator: A data quality tool for eye tracking glasses. *Behavior Research Methods*. [doi: 10.3758/s13428-023-02105-5](https://doi.org/10.3758/s13428-023-02105-5)
119
+
120
+
121
+ This project has received funding from the European Union's Horizon Europe research and innovation funding program under grant agreement No 101072410, Eyes4ICU project.
122
+
123
+ <p align="center">
124
+ <img src="resources/Funded_by_EU_Eyes4ICU.png" alt="Funded by EU Eyes4ICU" width="500">
125
+ </p>
126
+
127
+ Giraffe icon downloaded from <a href="https://www.flaticon.com/free-icons/giraffe" title="giraffe icons">Flaticon, created by smalllikeart</a>
zarafe-1.0.1/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # Zarafe <img src="resources/app_icon.ico" alt="zarafe" width="30" height="30">
2
+
3
+ Zarafe is a video annotation tool designed for marking time events in eye tracking videos with gaze data visualization.
4
+
5
+ <p align="center">
6
+ <img src="resources/app.png" alt="EyE Annotation Tool Main Page" width="800">
7
+ </p>
8
+
9
+ ## Overview
10
+
11
+ This tool allows users to:
12
+ - Load directories containing worldCamera.mp4 recordings and gazeData.tsv files
13
+ - View eye tracking videos with gaze position overlays
14
+ - Create, mark and manage time-based event annotations
15
+ - Save annotations to CSV files for further analysis
16
+
17
+ ## Data Preparation
18
+
19
+ **Important**: Before using Zarafe, you need to convert your eye tracking data:
20
+
21
+ Zarafe uses [glassesValidator](https://github.com/dcnieho/glassesValidator) to import your eye tracking data. Some eye trackers require preprocessing before importing:
22
+
23
+ - **Pupil Labs**: Export from Pupil/Neon Player (disable World Video Exporter) or Pupil Cloud
24
+ - **Meta Project Aria Gen 1**: Process in Aria Studio with MPS eye gaze run, then use provided export script
25
+ - **SMI ETG**: Export raw data and scene video from BeGaze with specific settings
26
+
27
+ For detailed preprocessing instructions for your specific eye tracker, see the [glassesValidator preprocessing guide](https://github.com/dcnieho/glassesValidator?tab=readme-ov-file#eye-trackers).
28
+
29
+ The import process will generate the required worldCamera.mp4 and gazeData.tsv files.
30
+
31
+ Zarafe expects a specific directory structure with each recording in its own folder containing both files.
32
+
33
+ ## Installation
34
+
35
+ 1. Clone this repository:
36
+ ```bash
37
+ git clone https://github.com/mh-salari/zarafe.git
38
+ cd zarafe
39
+ ```
40
+
41
+ 2. Install dependencies (choose one method):
42
+
43
+ **Option A: Using uv (recommended)**
44
+ ```bash
45
+ # Install uv from https://docs.astral.sh/uv/getting-started/installation/
46
+
47
+ # Install dependencies
48
+ uv sync
49
+ ```
50
+
51
+ **Option B: Using pip**
52
+ ```bash
53
+ pip install -e .
54
+ ```
55
+
56
+ 3. Run the application:
57
+ ```bash
58
+ # With uv
59
+ uv run python main.py
60
+
61
+ # With pip
62
+ python main.py
63
+ ```
64
+
65
+ ## Notes
66
+
67
+ Zarafe was developed by Mohammadhossein Salari with assistance from Claude 3.7 Sonnet, an AI assistant developed by Anthropic. Please be aware that this software is primarily for internal purposes and is not thoroughly documented.
68
+
69
+
70
+ ## License
71
+
72
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
73
+
74
+ ## Acknowledgments
75
+
76
+
77
+ Zarafe uses glassesValidator for data import. If you use this functionality, please cite:
78
+
79
+ Niehorster, D.C., Hessels, R.S., Benjamins, J.S., Nyström, M. and Hooge, I.T.C. (2023). GlassesValidator: A data quality tool for eye tracking glasses. *Behavior Research Methods*. [doi: 10.3758/s13428-023-02105-5](https://doi.org/10.3758/s13428-023-02105-5)
80
+
81
+
82
+ This project has received funding from the European Union's Horizon Europe research and innovation funding program under grant agreement No 101072410, Eyes4ICU project.
83
+
84
+ <p align="center">
85
+ <img src="resources/Funded_by_EU_Eyes4ICU.png" alt="Funded by EU Eyes4ICU" width="500">
86
+ </p>
87
+
88
+ Giraffe icon downloaded from <a href="https://www.flaticon.com/free-icons/giraffe" title="giraffe icons">Flaticon, created by smalllikeart</a>
@@ -0,0 +1 @@
1
+ # Build tools package
@@ -0,0 +1,34 @@
1
+ # PyInstaller Build Tools
2
+
3
+ This directory contains custom PyInstaller hooks and build configuration for creating macOS application bundles.
4
+
5
+ ## Build Commands
6
+
7
+ ### Create macOS Application Bundle
8
+ ```bash
9
+ uv run pyinstaller --onedir --windowed --name Zarafe --icon=resources/app_icon.icns --add-data "resources:resources" --additional-hooks-dir build-tools/pyinstaller-hooks --runtime-hook build-tools/pyinstaller-hooks/pyi_rth_ffmpeg.py main.py
10
+ ```
11
+
12
+ **Note**: This requires the custom PyInstaller hook files:
13
+ - `hook-ffmpeg.py` - Collects ffmpeg package data files
14
+ - `pyi_rth_ffmpeg.py` - Runtime hook that creates the ffmpeg module with add_to_path functionality
15
+
16
+ ### Test the Built Application
17
+ ```bash
18
+ ./dist/Zarafe.app/Contents/MacOS/Zarafe
19
+ ```
20
+
21
+ ## Files in this directory
22
+
23
+ - **hook-ffmpeg.py**: Custom PyInstaller hook that collects data files from the ffmpeg-binaries package
24
+ - **pyi_rth_ffmpeg.py**: Runtime hook that creates a mock ffmpeg module with the required `add_to_path()` method for glassesTools compatibility
25
+ - **README.md**: This documentation file
26
+
27
+ ## How it works
28
+
29
+ The ffmpeg-binaries package used by glassesTools is missing its `__init__.py` file and the required API methods. Our custom hooks solve this by:
30
+
31
+ 1. **hook-ffmpeg.py**: Ensures all ffmpeg package data files are included in the bundle
32
+ 2. **pyi_rth_ffmpeg.py**: Creates a runtime shim that provides the missing `add_to_path()` method that glassesTools expects
33
+
34
+ This approach allows the application to work both in development (via the compatibility module in `zarafe/utils/ffmpeg_compat.py`) and in the bundled PyInstaller environment.
@@ -0,0 +1 @@
1
+ # PyInstaller hooks package
@@ -0,0 +1,12 @@
1
+ """PyInstaller hook for ffmpeg-binaries package."""
2
+
3
+ from PyInstaller.utils.hooks import collect_data_files, get_package_paths
4
+
5
+ # Collect all data files from the ffmpeg package
6
+ datas = collect_data_files("ffmpeg")
7
+
8
+ # Get package path to include the package structure
9
+ package_dir, package_path = get_package_paths("ffmpeg")
10
+
11
+ # Include the executable and internals directories
12
+ datas += [(package_path, "ffmpeg")]
@@ -0,0 +1,60 @@
1
+ # Runtime hook for ffmpeg-binaries package
2
+
3
+ import os
4
+ import sys
5
+
6
+
7
+ def create_ffmpeg_module() -> None:
8
+ """Create the ffmpeg module with add_to_path functionality."""
9
+
10
+ # Create a mock ffmpeg module that provides the add_to_path function
11
+ class FFmpegModule:
12
+ def __init__(self) -> None:
13
+ self.FFMPEG_PATH = None
14
+ self._init_ffmpeg_path()
15
+
16
+ def _init_ffmpeg_path(self) -> None:
17
+ """Initialize the FFmpeg path."""
18
+ # In PyInstaller, look for ffmpeg binary in the bundle
19
+ if getattr(sys, "frozen", False):
20
+ # Running in a bundle
21
+ bundle_dir = getattr(sys, "_MEIPASS", os.path.dirname(sys.executable))
22
+ possible_paths = [
23
+ os.path.join(bundle_dir, "ffmpeg", "binaries", "ffmpeg"),
24
+ os.path.join(bundle_dir, "ffmpeg", "ffmpeg"),
25
+ os.path.join(bundle_dir, "Frameworks", "ffmpeg", "binaries", "ffmpeg"),
26
+ ]
27
+
28
+ for path in possible_paths:
29
+ if os.path.isfile(path):
30
+ self.FFMPEG_PATH = path
31
+ break
32
+
33
+ def add_to_path(self) -> None:
34
+ """Add ffmpeg binaries to PATH."""
35
+ if self.FFMPEG_PATH:
36
+ ffmpeg_dir = os.path.dirname(self.FFMPEG_PATH)
37
+ if ffmpeg_dir not in os.environ.get("PATH", ""):
38
+ os.environ["PATH"] = ffmpeg_dir + os.pathsep + os.environ.get("PATH", "")
39
+
40
+ def init(self) -> None:
41
+ """Initialize the module."""
42
+
43
+ def run_as_ffmpeg(self, args):
44
+ """Run ffmpeg with arguments."""
45
+ import subprocess
46
+
47
+ if self.FFMPEG_PATH:
48
+ return subprocess.run([self.FFMPEG_PATH, *args], check=False)
49
+ raise RuntimeError("FFmpeg binary not found")
50
+
51
+ # Create the module instance
52
+ ffmpeg_module = FFmpegModule()
53
+
54
+ # Add it to sys.modules
55
+ sys.modules["ffmpeg"] = ffmpeg_module
56
+
57
+
58
+ # Only run this if we're in a frozen environment and ffmpeg isn't already available
59
+ if getattr(sys, "frozen", False) and "ffmpeg" not in sys.modules:
60
+ create_ffmpeg_module()
zarafe-1.0.1/main.py ADDED
@@ -0,0 +1,41 @@
1
+ """Zarafe - Video annotation tool for eye tracking studies."""
2
+
3
+ import os
4
+ import sys
5
+
6
+ # Suppress Qt multimedia debug output - must be set before Qt imports
7
+ os.environ["QT_LOGGING_RULES"] = "qt.multimedia*=false"
8
+
9
+ # Patch ffmpeg module before any other imports that might use it
10
+ from zarafe.utils import ffmpeg_compat # noqa: F401 I001
11
+
12
+ from PyQt6.QtWidgets import QApplication
13
+
14
+ from zarafe.main_window import VideoAnnotator
15
+ from zarafe.utils.theme import apply_dark_theme
16
+ from zarafe.widgets.project_dialog import ProjectDialog
17
+
18
+
19
+ def main() -> None:
20
+ """Main application entry point."""
21
+ app = QApplication(sys.argv)
22
+ apply_dark_theme(app)
23
+
24
+ # Show project selection dialog first
25
+ project_dialog = ProjectDialog()
26
+ if project_dialog.exec() != ProjectDialog.DialogCode.Accepted:
27
+ # User cancelled project selection
28
+ sys.exit(0)
29
+
30
+ # Get selected project info
31
+ project_path, project_config = project_dialog.get_project_info()
32
+
33
+ # Create and show main window with the selected project
34
+ window = VideoAnnotator(project_path, project_config)
35
+ window.show()
36
+
37
+ sys.exit(app.exec())
38
+
39
+
40
+ if __name__ == "__main__":
41
+ main()