Skip to main content

HeatMatch

Visualize and compare very dense saccade patterns from long free-viewing eye-tracking data.

HeatMatch turns hundreds or thousands of saccades into continuous orientation fields: at every location it estimates saccade density, mean orientation, and how consistently the saccades agree in orientation. From these fields it draws orientation-coded heatmaps that show where gaze moves and in which direction. It also computes a similarity score for comparing saccade patterns across participants, stimuli, or conditions, without AOIs, scanpath alignment, or manual segmentation.

It was developed for 60-second viewing of paintings (empirical aesthetics, art history) and works for any static stimulus. Python implementation accompanying the paper:

Xingyu Long, Jozsef Arato, Sophia Kury, Anna Miscena, and Raphael Rosenberg. 2026.
HeatMatch: Orientation-Aware Visualization and Comparison of Very Dense Saccade Patterns.
Proceedings of the ACM on Computer Graphics and Interactive Techniques (PACMCGIT), 9(2), Article 18.
https://doi.org/10.1145/3803539
CReA Lab and Vienna Cognitive Science Hub

Overview

  1. OOI-coded heatmaps — orientation fields visualized with researcher-defined color anchors and confidence-weighted opacity.
  2. HeatMatch similarity — comparison based on saccade density and orientation.

HeatMatch heatmap example Per-participant (columns 1–5) and aggregated (column 6) heatmaps for three paintings. Hue = mean saccade orientation relative to OOI; opacity = local confidence. Stimulus images: public domain via Wikimedia Commons — see paper for details.

See the paper for methodology.

When to use it

  • Long, dense viewing. Scanpath comparison methods such as MultiMatch or ScanMatch align scanpaths sequence by sequence. With hundreds of saccades per trial and strongly diverging paths, they become slow and hard to interpret. HeatMatch aggregates instead of aligning, so it scales to arbitrarily dense data.
  • Orientation matters. Fixation heatmaps and density-based metrics ignore saccade direction. HeatMatch keeps orientation, so you can ask whether gaze follows horizontal, vertical, diagonal, or symmetric structure in an image, e.g. composition lines in a painting.
  • Group, stimulus, and individual comparisons. In the paper, the similarity score recovers the abstract vs. still-life distinction and differences in within-painting agreement. It also reveals stable individual "saccadic signatures" that hold across paintings.

It is not a replacement for sequence-based methods. HeatMatch is permutation-invariant (it ignores saccade order) and treats orientations as unsigned (left-to-right = right-to-left). Use it alongside MultiMatch, ScanMatch, or RQA when order or direction matters.


Installation

pip install heatmatch

Dependencies: numpy, matplotlib, Pillow. For development, clone the repository and run pip install -e ..


Quick Start

import matplotlib.pyplot as plt
from heatmatch import make_reference_grid, make_orientation_field, Heatmap, compute_similarity

W, H = 2880, 2160
onset  = ...  # (J, 2) saccade start coordinates
offset = ...  # (J, 2) saccade end coordinates

pts, xx, yy = make_reference_grid(W, H, grid_resolution=200)
field = make_orientation_field(pts, onset, offset, sigma=50.0, grid_shape=yy.shape)

fig, ax = plt.subplots()
Heatmap(field, W, H).draw(ax, ooi=0.0)  # ooi=0 → horizontal, ooi=90 → vertical
plt.show()

# Compare two patterns (fields built on the same grid, e.g. two participants)
result = compute_similarity(field_a, field_b)
s = (result.s_loc + result.s_dir) / 2  # composite HeatMatch score S in [0, 1]
print(result.s_loc, result.s_dir, s)

A full worked example is in demo.ipynb. The dataset is not included — download data_anonymized.csv from osf.io/f2xhj and place it in tests/.


API

heatmatch.fields

make_reference_grid(w, h, grid_resolution) Returns (pts, xx, yy); int → square grid, (ny, nx) tuple → rectangular
make_orientation_field(pts, onset, offset, sigma, grid_shape, ...) Returns OrientationField with omega_mean, R, rho

heatmatch.heatmapping

Heatmap(field, w, h, image=None) Caches colormap, opacity, and (optionally) grayscale background image
Heatmap.draw(ax, ooi, opacity_density_weight, base_opacity, cmap, ...) Renders onto ax

OOI in degrees: 0 = east, 90 = north, 180 = west, 270 = south. Unsigned, so ooi and ooi ± 180 are equivalent.

heatmatch.matching

compute_similarity(field_a, field_b, density_coherence_tradeoff) Returns SimilarityResult(s_loc, s_dir)

Key Parameters

Parameter Default Notes
sigma 50.0 Gaussian bandwidth in px. Paper evaluates {50, 100, 150}.
grid_resolution 200 Int or (ny, nx). Paper uses 200.
ooi 0.0 Orientation of Interest in degrees.
opacity_density_weight 1.0 Density vs. coherence for opacity. Recommended 0.5–1.0.
base_opacity 0.85 Global opacity ceiling; useful with a background image.
density_coherence_tradeoff 0.5 Density vs. coherence for S_dir. At 1.0, angular information is discarded.

Citation

@article{long2026heatmatch,
  author    = {Long, Xingyu and Arato, Jozsef and Kury, Sophia and Miscena, Anna and Rosenberg, Raphael},
  title     = {HeatMatch: Orientation-Aware Visualization and Comparison of Very Dense Saccade Patterns},
  journal   = {Proc. ACM Comput. Graph. Interact. Tech.},
  year      = {2026},
  volume    = {9},
  number    = {2},
  articleno = {18},
  doi       = {10.1145/3803539},
}

Metadata

Release files for heatmatch 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for heatmatch 1.0.0
File Size Uploaded
heatmatch-1.0.0.tar.gz 14.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for heatmatch 1.0.0
File Interpreter ABI Platform
heatmatch-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 26.5 kB

Release files / heatmatch-1.0.0.tar.gz

Download URL heatmatch-1.0.0.tar.gz
Size 14.1 kB
Tags Source
SHA-256 checksum
How to use checksums
753b324c2abe0096360935867b098a8c1ebc397efd0a697b41f115c77822a407
BLAKE2b-256 checksum
How to use checksums
497ba48f28dbd1078b5f8c1275446d79391cb0dd3c25cf2e8689d0ef00c3ff11
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.2

Release files / heatmatch-1.0.0-py3-none-any.whl

Download URL heatmatch-1.0.0-py3-none-any.whl
Size 12.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
80d206daab3663353fa673000d0d0d1a4a3cb77c6ae94e010e0e608304247ff4
BLAKE2b-256 checksum
How to use checksums
934966fd5041bdc0acae6b3546b6bd4bbda3e7ddc34436b86407d7666795c182
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.2

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page