Development¶
Setup¶
pip install -e ".[gui,plot,logger,hrv,dev]"
pytest
The logger's tests (tests/test_logger.py) use simulated sensors, a fake lux board and a slow disk, so they need no
hardware and no Bluetooth; the Shimmer and EmotiBit paths were checked by hand on real devices. To run the logger's
window headless, set QT_QPA_PLATFORM=offscreen.
The tests build synthetic recordings for every device (tests/conftest.py: write_varjo_recording,
write_core_recording, write_neon_recording, write_tobii_g3_recording) with known pupil, gaze and scene colours, so they run without real
data. The GUI tests need a display or QT_QPA_PLATFORM=offscreen.
Conventions¶
- The analysis (
cwtool/, exceptgui/andlogger/gui.py) does not import Qt, so it runs headless and in scripts. - Qt code imports PySide6 before pyqtgraph (
logger/gui.pyalso setsPYQTGRAPH_QT_LIB): with PyQt6 also installed, pyqtgraph would load it and two Qt copies in one process crash. - Hardware calls that can block (device discovery, connecting) run in a background task, never in the window's thread; disk writes of the logger run in their own thread.
- Readers return NaN for invalid samples; the pipeline never sees device-specific validity flags.
- Parameters that do not change the video pass belong in
Parameters; those that do belong inVideoSettings(and are part of the cache key). - Every
Parametersfield needs an editor ingui/param_panel.py; a check at start-up enforces it. - Changing what the video pass stores means bumping
CACHE_FORMATinvideo.py. - Inconsistencies found in the code, the data or the papers go in
docs/OPEN_ISSUES.md.
Comments¶
- Every source file starts with a header saying what it contains: the module docstring of a Python file (tests
included), a
//comment at the top of an Arduino sketch, a comment in the page for the calibration presenter, the settings and the workflow. Keep it to what the file is for and what it does not do, not a list of its functions. - Every public class and function has a docstring (one line is enough when the name and the arguments say the rest): what it returns and the units (s, mm, cd/m²) and the clock a time is on, where that is not obvious. Private helpers get one when their logic is not clear from the code.
- Comments explain why, not what: the assumption behind a number, the reason for an order of operations, the open
issue a workaround refers to (
issue 47). Tests are named after what they check and need no docstring. - A docstring that disagrees with the code is a bug: change both together.
Icons¶
The windows use Tabler's outline icons (MIT; the licence is in cwtool/gui/icons/), stored as SVG files and drawn
by cwtool.gui.icons.icon(name, size) in the colours of the current palette, at twice the resolution on high-DPI
screens. To add one, copy its SVG from tabler.io/icons (outline) into cwtool/gui/icons/,
add its name to NAMES in icons.py and use icon("name"); a test checks that every named icon has a clean file
and that no file is left unnamed. The SVGs are included in the installed package (package-data in pyproject.toml).
Documentation¶
This site is built with MkDocs and the Material theme from docs/ and mkdocs.yml.
pip install -r docs/requirements.txt
mkdocs serve # live preview at http://127.0.0.1:8000
mkdocs build --strict # what the deployment runs
Pushes to master_v2.0 that touch the docs publish the site to GitHub Pages through .github/workflows/docs.yml
(repository Settings → Pages → Source: GitHub Actions).