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.
- zarafe-1.0.1/.claude/settings.local.json +8 -0
- zarafe-1.0.1/.gitignore +176 -0
- zarafe-1.0.1/CLAUDE.md +36 -0
- zarafe-1.0.1/LICENSE +21 -0
- zarafe-1.0.1/PKG-INFO +127 -0
- zarafe-1.0.1/README.md +88 -0
- zarafe-1.0.1/build-tools/__init__.py +1 -0
- zarafe-1.0.1/build-tools/pyinstaller-hooks/README.md +34 -0
- zarafe-1.0.1/build-tools/pyinstaller-hooks/__init__.py +1 -0
- zarafe-1.0.1/build-tools/pyinstaller-hooks/hook-ffmpeg.py +12 -0
- zarafe-1.0.1/build-tools/pyinstaller-hooks/pyi_rth_ffmpeg.py +60 -0
- zarafe-1.0.1/main.py +41 -0
- zarafe-1.0.1/pyproject.toml +149 -0
- zarafe-1.0.1/resources/Funded_by_EU_Eyes4ICU.png +0 -0
- zarafe-1.0.1/resources/app.png +0 -0
- zarafe-1.0.1/resources/app_icon.icns +0 -0
- zarafe-1.0.1/resources/app_icon.ico +0 -0
- zarafe-1.0.1/resources/giraffe.png +0 -0
- zarafe-1.0.1/resources/icons/add_circle.svg +1 -0
- zarafe-1.0.1/resources/icons/arrow_down.svg +1 -0
- zarafe-1.0.1/resources/icons/arrow_up.svg +1 -0
- zarafe-1.0.1/resources/icons/chevron_left.svg +1 -0
- zarafe-1.0.1/resources/icons/chevron_right.svg +1 -0
- zarafe-1.0.1/resources/icons/delete.svg +1 -0
- zarafe-1.0.1/resources/icons/edit.svg +1 -0
- zarafe-1.0.1/resources/icons/mark_end.svg +1 -0
- zarafe-1.0.1/resources/icons/mark_start.svg +1 -0
- zarafe-1.0.1/resources/icons/mute.svg +1 -0
- zarafe-1.0.1/resources/icons/pause.svg +1 -0
- zarafe-1.0.1/resources/icons/play.svg +1 -0
- zarafe-1.0.1/resources/icons/save.svg +1 -0
- zarafe-1.0.1/resources/icons/volume.svg +1 -0
- zarafe-1.0.1/resources/icons/warning.svg +1 -0
- zarafe-1.0.1/uv.lock +1835 -0
- zarafe-1.0.1/zarafe/__init__.py +3 -0
- zarafe-1.0.1/zarafe/controllers/__init__.py +1 -0
- zarafe-1.0.1/zarafe/controllers/main_controller.py +83 -0
- zarafe-1.0.1/zarafe/controllers/project_controller.py +123 -0
- zarafe-1.0.1/zarafe/controllers/video_navigation_controller.py +45 -0
- zarafe-1.0.1/zarafe/core/__init__.py +1 -0
- zarafe-1.0.1/zarafe/core/audio_manager.py +62 -0
- zarafe-1.0.1/zarafe/core/color_theme_manager.py +47 -0
- zarafe-1.0.1/zarafe/core/config.py +55 -0
- zarafe-1.0.1/zarafe/core/configuration_service.py +57 -0
- zarafe-1.0.1/zarafe/core/event_manager.py +252 -0
- zarafe-1.0.1/zarafe/core/event_type_registry.py +51 -0
- zarafe-1.0.1/zarafe/core/gaze_data.py +38 -0
- zarafe-1.0.1/zarafe/core/shortcut_manager.py +56 -0
- zarafe-1.0.1/zarafe/core/video_manager.py +121 -0
- zarafe-1.0.1/zarafe/main_window.py +453 -0
- zarafe-1.0.1/zarafe/utils/__init__.py +1 -0
- zarafe-1.0.1/zarafe/utils/ffmpeg_compat.py +55 -0
- zarafe-1.0.1/zarafe/utils/file_utils.py +26 -0
- zarafe-1.0.1/zarafe/utils/icon_loader.py +88 -0
- zarafe-1.0.1/zarafe/utils/importer.py +148 -0
- zarafe-1.0.1/zarafe/utils/sorting.py +19 -0
- zarafe-1.0.1/zarafe/utils/theme.py +186 -0
- zarafe-1.0.1/zarafe/widgets/__init__.py +1 -0
- zarafe-1.0.1/zarafe/widgets/about_dialog.py +62 -0
- zarafe-1.0.1/zarafe/widgets/base_dialog.py +213 -0
- zarafe-1.0.1/zarafe/widgets/event_controls.py +113 -0
- zarafe-1.0.1/zarafe/widgets/menu_manager.py +76 -0
- zarafe-1.0.1/zarafe/widgets/metadata_panel.py +22 -0
- zarafe-1.0.1/zarafe/widgets/new_project_dialog.py +721 -0
- zarafe-1.0.1/zarafe/widgets/panels/__init__.py +1 -0
- zarafe-1.0.1/zarafe/widgets/panels/left_panel.py +54 -0
- zarafe-1.0.1/zarafe/widgets/panels/main_layout_manager.py +76 -0
- zarafe-1.0.1/zarafe/widgets/project_dialog.py +291 -0
- zarafe-1.0.1/zarafe/widgets/pupil_plot.py +136 -0
- zarafe-1.0.1/zarafe/widgets/video_controls.py +84 -0
- zarafe-1.0.1/zarafe/widgets/video_display.py +189 -0
zarafe-1.0.1/.gitignore
ADDED
|
@@ -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()
|