Skip to main content

Interactive Streamlit workbench for visualizing eye-tracking-while-reading scanpaths, computing reading measures, and exporting figures and tabular data.

This project has been archived.

The maintainers of this project have marked this project as archived. No new releases are expected.

Project description

Scanpath Visualization

PyPI Live demo CI License: MIT

Interactive Streamlit workbench for exploring eye-tracking-while-reading scanpaths. The tool renders word boxes, fixations, saccades, density heatmaps, side-by-side trial comparisons, scarf plots, and per-word reading measures. It computes the canonical reading measures (FFD, FPRT/gaze duration, RPD/go-past, TFD/dwell, regressions) from first principles when the input only carries raw fixations, and surfaces NLP-relevant linguistic features (GPT-2 surprisal, word frequency, POS) shipped with the OneStop corpus.

Authors: Omer Shubi, LACC Lab (Technion). Demo corpus: OneStop Eye Movements (Berzak, Malmaud, Shubi, Meiri, Lion, Levy, Scientific Data 2025) — a 360-participant English eye-tracking dataset with multiple reading regimes. A subset of three participants reading two articles across both Adv and Ele difficulty levels is bundled with the wheel.


Quick start

Try the live demo

A hosted instance is available on Streamlit Community Cloud: https://scanpath-visualization.streamlit.app

Install from PyPI

pip install scanpath-visualization-app
scanpath-visualization              # launches the Streamlit UI
# or
python -m scanpath_visualization_app

Run from source

git clone https://github.com/lacclab/scanpath-visualization.git
cd scanpath-visualization

# Option 1 — uv (fastest)
uv sync
uv run streamlit run streamlit_app.py

# Option 2 — pip in editable mode
pip install -e ".[test]"
streamlit run streamlit_app.py

# Option 3 — conda / mamba
mamba env create -f environment.yml
mamba activate scanpath-visualization
streamlit run streamlit_app.py

Tested on Python 3.11 – 3.13.


What the tool does

The app organizes work into five tabs:

Tab Purpose
Interactive Plot Layered scanpath view (word boxes, fixations colored by any feature, saccades, density heatmap, optional raw-gaze trail). Trial picker by trial / by text / by participant. Optional overlay or side-by-side comparison of two trials.
Reading Measures Scarf plot (per-fixation timeline), per-IA measure bar plot (FFD / FPRT / RPD / TFD / surprisal / frequency / ...), fixation-duration distribution.
Animated Scanpath Frame-by-frame replay where each frame's duration is the actual fixation duration divided by playback speed.
Raw Data Paginated tables for words, fixations, and raw gaze, each with per-table CSV + Parquet download buttons.
Data Statistics Reading-research summaries: mean fixation duration, mean saccade amplitude, regression rate, reading speed (wpm), plus distributions of trials/fixations/words across the filtered set.

Computed reading measures

When the input table doesn't include EyeLink IA-aggregated columns (or you upload raw fixations from a non-EyeLink pipeline), the tool computes the following per (participant, trial, word) from fixations + word bounding boxes:

Column Reading-research name Definition (Rayner 1998; Inhoff & Radach 1998)
first_fixation_ms FFD — first fixation duration duration of the very first fixation that lands on the word
first_pass_gaze_duration_ms FPRT / gaze duration sum of fixations from first entry until first leave (forward or backward)
regression_path_duration_ms RPD / go-past time sum of all fixations from first entry until the eye first lands strictly past the word
total_fixation_duration_ms TFD / dwell sum of all fixations on the word
n_fixations fixation count total fixations on the word
skip_flag skip True if the word never received a first-pass fixation
regression_in_flag regression in True if a fixation arrived from a later word
regression_out_flag regression out True if a fixation on the word was followed by a fixation on an earlier word
saccade_amplitude saccade amplitude (px) euclidean distance from previous fixation

If your table already carries pre-aggregated measures (e.g. EyeLink IA_FIRST_FIXATION_DURATION), those values win — computation is a fallback.


Bulk export

The Interactive tab has a configurable Bulk export panel that bundles artifacts for every filtered trial into a single zip:

scanpath_export_<timestamp>.zip
├─ README.md
├─ per_trial/
│  └─ <participant>__<trial>/
│     ├─ figure.png            (raster, scale 1–4×)
│     ├─ figure.svg            (vector — paper figures)
│     ├─ plot_config.json      (reproducible plot settings)
│     ├─ fixations.csv         (or .parquet)
│     └─ measures.csv          (per-word measures, csv/parquet)
└─ aggregate/
   ├─ all_fixations.csv        (long-form across trials)
   └─ all_measures.csv

Each artifact has its own checkbox so you can export only what you need.


Data expectations

The app auto-detects column names from common eye-tracking export conventions. Upload CSV, Parquet, or Feather tables. Both file formats work for the words/IA file, the fixations file, and the optional raw-gaze file.

Required columns (auto-detected from EyeLink / Gazepoint / snake_case):

Table Required Common candidates
Words/IA participant, trial, word ID, bounding box participant_id / subject_id; unique_trial_id / trial_id; IA_ID / word_id; either (x, y, width, height) or (IA_LEFT, IA_RIGHT, IA_TOP, IA_BOTTOM)
Fixations participant, trial, x, y, duration CURRENT_FIX_X/Y/DURATION (EyeLink), FPOGX/FPOGY (Gazepoint), or snake_case
Raw gaze (optional) participant, trial, x, y snake_case or FPOGX/FPOGY

After upload, the sidebar shows Column mapping expanders — you can override any auto-detected mapping if your columns don't match the common candidates.


Development

# Install with test deps
pip install -e ".[test]"

# Run all tests
pytest

# Lint + format
ruff check --exclude other_vis .
ruff format --exclude other_vis .

# Regenerate bundled sample data (requires the full OneStop CSVs locally)
python -m scanpath_visualization_app.update_sample_data

See AGENTS.md for the architectural overview Claude / Copilot use when modifying this code.


Citation

If you use this tool, please cite both the demo paper (placeholder — replace once published) and the OneStop corpus:

@inproceedings{shubi2026scanpath,
  title     = {Scanpath Visualization: An Interactive Workbench for Reading
               Eye-Tracking Data},
  author    = {Shubi, Omer and others},
  booktitle = {Proceedings of the *CL Conference, System Demonstrations},
  year      = {2026},
}

@article{berzak2025onestop,
  title     = {{OneStop}: A 360-Participant {E}nglish Eye Tracking Dataset
               with Different Reading Regimes},
  author    = {Berzak, Yevgeni and Malmaud, Jonathan and Shubi, Omer
               and Meiri, Yoav and Lion, Ella and Levy, Roger},
  journal   = {Scientific Data},
  year      = {2025},
  publisher = {Nature Publishing Group},
  doi       = {10.1038/s41597-025-06272-2},
  url       = {https://www.nature.com/articles/s41597-025-06272-2},
}

The bundled demo data is a subset of OneStop Eye Movements, used here under its original license. The corpus documentation is at https://lacclab.github.io/OneStop-Eye-Movements/.


License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

scanpath_visualization_app-0.9.1.tar.gz (582.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

scanpath_visualization_app-0.9.1-py3-none-any.whl (577.1 kB view details)

Uploaded Python 3

File details

Details for the file scanpath_visualization_app-0.9.1.tar.gz.

File metadata

File hashes

Hashes for scanpath_visualization_app-0.9.1.tar.gz
Algorithm Hash digest
SHA256 54000995fc902cef18cc0884a82061d1362d2479ac67de06e01f5083ebf116bc
MD5 091bab433aafce6c6fe8b135d12f54a2
BLAKE2b-256 eb6c4e469a52cf4c6f6ede6323ee17416561c1f4d696991759e78f19e3cda6b7

See more details on using hashes here.

Provenance

The following attestation bundles were made for scanpath_visualization_app-0.9.1.tar.gz:

Publisher: publish.yml on lacclab/scanpath-visualization

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file scanpath_visualization_app-0.9.1-py3-none-any.whl.

File metadata

File hashes

Hashes for scanpath_visualization_app-0.9.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4505a15d276c55bf3e6980eb5d6b5345bf34fa9ab3055081eb4d16641075adbe
MD5 a212932026d47e84a49fe21bd069e577
BLAKE2b-256 5429933195330274b05a6609604fa97390a106aaac8c3a35c2d3240a6afc6878

See more details on using hashes here.

Provenance

The following attestation bundles were made for scanpath_visualization_app-0.9.1-py3-none-any.whl:

Publisher: publish.yml on lacclab/scanpath-visualization

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page