Skip to content

CLI reference

scanpath-studio launches the app. Its subcommands do the rest without opening it:

Command What it does
scanpath-studio, run Launch the app
render Write one trial's scanpath, heatmap or replay to a file
corpus Render a corpus figure from a tidy CSV you already have
check Run the Data checks on your tables
cache Show or clear the recovery cache
version Show the build, and whether a newer release is out
cite Print how to cite Scanpath Studio

Each command takes --help, and scanpath-studio --version prints the version. A word that is not a command is an error that suggests the closest command. It is not passed on to Streamlit.

Launch the app

scanpath-studio
scanpath-studio --server.port 8600
scanpath-studio --no-persist          # don't cache the session on this computer
scanpath-studio --download-dir D:\corpora  # where ⬇ Download saves public datasets

scanpath-studio run … is the same. Any other launch flag is passed on to streamlit run.

The app listens on this computer only (127.0.0.1), and it has no login. To serve it to other machines on a network you trust, pass --server.address 0.0.0.0, or set server.address in a Streamlit config.toml or STREAMLIT_SERVER_ADDRESS:

scanpath-studio --server.address 0.0.0.0

Served on a network, the app turns off the controls that read or write the server's folders, because any visitor could use them. These are the Data directory box, the folder picker, and ⬇ Download for the public datasets and stimulus-image folders. On a lab server you trust, turn them back on with SCANPATH_LOCAL_FS=1 (SCANPATH_LOCAL_FS=1 scanpath-studio --server.address 0.0.0.0).

render

render writes one trial to a file without opening the app. The extension picks the format: .html is interactive and needs nothing else, while .png, .svg and .pdf need Chrome, Chromium or Edge (or run plotly_get_chrome -y once; see the FAQ). The figure is the app's Scanpath design unless a flag changes it, and every figure option has a flag.

# List the trials to pick from
scanpath-studio render --sample --list-trials

# The bundled demo
scanpath-studio render --sample -o scanpath.html

# Your own data (replace p1 / t3 with IDs from --list-trials)
scanpath-studio render \
  --words ia.csv --fixations fixations.csv \
  --participant p1 --trial t3 --output scanpath.svg

# A draft file saved from the app's Draw a scanpath screen
scanpath-studio render --authoring authored-scanpath.json -o authored.html

# A public dataset, loaded as the app loads it (downloaded on first use)
scanpath-studio render --potec ./potec --list-trials
scanpath-studio render --onestop ./onestop --onestop-variant public \
  --onestop-regime ordinary --onestop-part Paragraph --list-trials

The Python API loads the same datasets with load_potec and load_onestop.

Common tasks

Goal Flags
add a layer --word-boxes, --fixation-index, --heatmap
hide a layer --no-text, --no-fixations, --no-saccades
animate --animate, optionally --playback-speed X. The replay uses every styling flag it can draw and names the rest in a warning
set the screen size --canvas WIDTHxHEIGHT. --crop-to-data frames the data instead of the whole screen, with --crop-margin PX around it (default: 5% of the data's extent, at least 20 px)
color fixations --color-by FIELD, including a column of your own once --keep-columns COLUMN… carries it through loading
size fixations by duration --marker-size-scale sqrt\|linear\|log\|relative (default sqrt), --marker-duration-range LO HI (ms, default 50 600), --marker-size-range MIN MAX (px), --no-duration-size-legend
draw only part of a trial --fix-index-range START:END (1-based, both inclusive; --animate and --compare-with honor it too)
draw the stimulus --stimulus-image PATH for one image. --show-stimulus-image draws each trial's stimulus image, named in the image_path column (--sample ships its images). --image-root DIR --image-pattern '{text_id}.png' fills image_path from a folder
smooth the heatmap --heatmap-style smoothed --heatmap-sigma 20 (σ in px; leave it out for an automatic σ)
style the word boxes --word-box-color, --word-box-line-opacity, --word-box-fill-color, --word-box-fill-opacity. A fill opacity of 0 draws outlines only, and a line opacity of 0 the fill only
size the figure --width, --height, --scale. For print, --width-mm MM or --width-in IN with --dpi N (default 300)
add a title and caption --title, --caption
write each layer to its own file --separable-layers
print the equivalent code --print-code python (or cli / both), plus --print-code-explicit

Compare two scanpaths

--compare-with PARTICIPANT:TRIAL draws a second trial, B, beside or over the first. It does what the app's Compare does.

# Two participants on the same paragraph, overlaid
scanpath-studio render --sample -p l37_1129 -t l37_1129_2_1_1_Ele \
  --compare-with l7_1090:l7_1090_2_1_1_Ele -o compare.html

# The same overlay, drawing only B's word boxes and text
scanpath-studio render --sample -p l37_1129 -t l37_1129_2_1_1_Ele \
  --compare-with l7_1090:l7_1090_2_1_1_Ele --compare-stimulus b \
  -o compare_b.html

# Side by side: each panel draws its trial's stimulus
scanpath-studio render --sample -p l37_1129 -t l37_1129_2_1_1_Ele \
  --compare-with l7_1090:l7_1090_2_1_1_Ele \
  --compare-layout side-by-side -o compare.svg

# A style for each scanpath
scanpath-studio render --sample -p l37_1129 -t l37_1129_2_1_1_Ele \
  --compare-with l7_1090:l7_1090_2_1_1_Ele \
  --style-a fix_color=#D55E00,opacity=0.5 --style-b saccade_style=dash \
  -o compare_styled.html

# B from a second dataset
scanpath-studio render --words ia.csv --fixations fix.csv -p p1 -t t1 \
  --compare-with p1:t1 \
  --compare-words other/ia.csv --compare-fixations other/fix.csv \
  --compare-dataset-name "Our lab" \
  --canvas 1680x1050 --compare-canvas 1680x1050 \
  -o cross.html
Goal Flags
pick B --compare-with PARTICIPANT:TRIAL
pick each screen of a multipart trial --screen ID (A), --compare-screen ID (B); each defaults to its trial's first screen
arrange the panels --compare-layout {overlay,side-by-side,stacked} (default overlay)
choose whose stimulus an overlay draws --compare-stimulus {both,a,b} (default both)
name the two scanpaths --label-a TEXT --label-b TEXT (both or neither)
style each scanpath --style-a SPEC, --style-b SPEC (keys below)
leave out the A/B legend --no-compare-legend
give B a separate stimulus image (side by side or stacked) --stimulus-image-b PATH, with --stimulus-image-size-b WxH / --stimulus-image-origin-b X,Y
take B from another dataset --compare-words PATH… --compare-fixations PATH…, plus --compare-raw-gaze PATH… and --compare-dataset-name NAME
set the two screen sizes --canvas WxH, --compare-canvas WxH
replay both on one clock add --animate (HTML output)

--label-a / --label-b and --style-a / --style-b apply to the --animate replay too.

Style keys

--style-a and --style-b take a comma-separated KEY=VALUE list and can be repeated. They are the app's Scanpath A / Scanpath B rows and compare_scanpaths's style_a / style_b. A key left out keeps that scanpath's default.

Key Value Left out
fix_color #RRGGBB that scanpath's default
saccade_color #RRGGBB that scanpath's default
box_color #RRGGBB, the outline of that scanpath's word boxes its fix_color
box_fill_color #RRGGBB, the boxes' fill --word-box-fill-color
box_line_opacity, box_fill_opacity 0–1 --word-box-line-opacity, --word-box-fill-opacity
raw_gaze_color #RRGGBB, that scanpath's raw-gaze samples its fix_color
heatmap_colorscale a Plotly color scale; the range stays shared, and two different scales get a color bar each --heatmap-colorscale
saccade_style solid, dash, dot or dashdot that scanpath's default
saccade_width px that scanpath's default
marker_size_range MIN:MAX that scanpath's default
opacity 0.1–1 that scanpath's default
hollow true or false that scanpath's default

The --animate replay draws one set of word boxes and no raw gaze, so it ignores the box_* keys and raw_gaze_color.

What a comparison can't combine

  • --compare-with cannot be combined with --all-screens or --screens. A comparison is one figure of two trials, each drawn from one screen. B's --compare-screen is looked up in B's trial, so it can be a later screen, or a screen of the second dataset.
  • An overlay of two datasets needs matching canvases. On two different canvases, --compare-layout overlay exits with an error, and so does --animate, which replays both scanpaths in one coordinate space. Use --compare-layout side-by-side or stacked, without --animate. Two screens of one dataset with different canvases are refused the same way. Nothing is rescaled.
  • Without --compare-canvas, the second dataset's screen size is estimated from its data, as A's is when neither --canvas nor a built-in source gives one. The data rarely spans the whole screen, so give both screen sizes when you know them.
  • A second dataset can only be loaded from files. In Python, compare_scanpaths takes B's frames directly, so any dataset you can load can be B.

Raw gaze

--raw-gaze PATH… reads a Raw gaze table, with its columns auto-detected like --fixations, and draws the plotted trial's samples under the fixations. With --compare-with it covers both scanpaths, each in its scanpath's color. --compare-raw-gaze PATH… gives B's samples when B comes from another dataset. --animate ignores raw gaze with a warning.

scanpath-studio render --sample -p l37_1129 -t l37_1129_2_2_2_Adv \
  --sample-raw-gaze --raw-gaze-opacity 0.4 -o raw_gaze.html

When --raw-gaze is the only input, it is the dataset. --list-trials lists its trials, and render draws the chosen trial's samples as recorded. No fixations are detected from them, so --animate and --compare-with exit with an error that says so.

scanpath-studio render --raw-gaze gaze_samples.csv --list-trials
scanpath-studio render --raw-gaze gaze_samples.csv -t t3 -o samples.png

Multipart trials and many trials

render writes one trial per run. For many figures, use the Python batch recipe or the Export bundle on the app's Export tab.

A multipart trial is the exception. --all-screens writes one __screen-001-<id> file per screen of the selected trial, and --screens Title,Paragraph writes only the screens named, each still numbered by its place in the trial. When your tables have no screen column, --trial-parts-manifest manifest.json assigns source rows to screens.

scanpath-studio render --words ia.csv --fixations fix.csv --list-parts
scanpath-studio render --words ia.csv --fixations fix.csv \
  -p p1 -t t3 --screen question -o question.svg
scanpath-studio render --words ia.csv --fixations fix.csv \
  -p p1 -t t3 --all-screens --animate --screen-transition recorded \
  -o replay.html

When a column isn't recognized

Column names are auto-detected (EyeLink, Tobii, SMI, Pupil Labs, Gazepoint and snake_case spellings). When one isn't, render stops and prints which field it could not find, the names it looked for, the columns your table has, and a mapping to start from. Pass that mapping back as JSON, inline or as a path to a .json file, with --word-schema (the --words table) and/or --fix-schema (the --fixations table). check takes the same two flags.

scanpath-studio render --words ia.csv --fixations fix.csv \
  --word-schema '{"trial": "TRIAL_LABEL", "word_id": "IA_ID", "text": "IA_LABEL",
                  "left": "IA_LEFT", "right": "IA_RIGHT", "top": "IA_TOP", "bottom": "IA_BOTTOM"}' \
  --fix-schema fix_schema.json -o scanpath.html

A mapping replaces auto-detection for that table, so it has to name every required field, not only the one that failed. It is the same dict load_scanpath_data(word_schema=…, fix_schema=…) takes in Python.

render flags

Every render flag, generated from the command's parser, with the defaults and help that --help prints. The figure flags are grouped like the figure options they set.

Trial and output

Option Value Default Description
-p
--participant
PARTICIPANT — Participant ID (default: the first).
-t
--trial
TRIAL — Trial ID (default: the participant's first).
--screen SCREEN — Screen ID within a multipart trial (default: the first screen).
--list-trials switch — Print every trial with its participant, trial and text IDs, then exit. Pass a trial ID to -t.
--list-parts switch — Print the screens of each multipart trial in order, then exit. -p and -t narrow the list.
--all-screens switch — Render every screen of the selected trial, one file each. The screen ID goes before the output's extension.
--screens ID[,ID...] — Like --all-screens, for only these screens: comma-separated screen IDs, e.g. Title,Paragraph. See --list-parts.
--screen-transition instant, recorded instant With --all-screens --animate: record no delay between screens (instant) or the recorded one (recorded) in each file's metadata (default: instant).
-o
--output
PATH — Output file. Its extension sets the format: .html, .png, .svg or .pdf.
--animate switch — Render the animated replay instead of the static figure (HTML only).

Input

Option Value Default Description
--sample switch — Use the bundled demo, from OneStop: 2 participants, 12 trials each (--list-trials shows them).
--authoring PATH — A draft file from the app's Draw a scanpath screen.
--words PATH [PATH ...] — The Words table: CSV, TSV, TXT, TAB, Parquet, Feather, XLSX or XLS, or a .zip of them. Columns are auto-detected from EyeLink, Gazepoint, Tobii, SMI, Pupil Labs and snake_case names. Several paths, or a quoted glob, are stacked into one table.
--fixations PATH [PATH ...] — The Fixations table, in the formats --words reads and auto-detected the same way. Several paths, or a quoted glob, are stacked into one table (e.g. one file per participant).
--image-root DIR — A folder of stimulus images. Each row's image is found with --image-pattern and stored in its image_path column. Add --show-stimulus-image to draw them. Works with every input, including --sample and the public datasets.
--image-pattern PATTERN {text_id}.png File name pattern inside --image-root, with column placeholders, e.g. '{text_id}.png' or '{participant_id}/{trial_id}.png'.
--trial-parts-manifest PATH — A JSON manifest that assigns source rows to the screens of each trial, in order. Use it with --words / --fixations when the tables have no screen column.
--word-schema JSON — Column mapping for the --words table, replacing auto-detection. A JSON object from each field to a column name, or the path of a JSON file holding one, e.g. '{"trial": "TRIAL_INDEX", "word_id": "IA_ID", ...}'. It is the dict api.load_scanpath_data takes. Needed only when a column isn't recognized, and the error then prints a mapping to start from.
--fix-schema JSON — Column mapping for the --fixations table, replacing auto-detection. A JSON object from each field to a column name, or the path of a JSON file holding one, e.g. '{"trial": "TRIAL_INDEX", "word_id": "IA_ID", ...}'. It is the dict api.load_scanpath_data takes. Needed only when a column isn't recognized, and the error then prints a mapping to start from.
--keep-columns COLUMN [COLUMN ...] — More columns to keep through loading, under the names they have in your files (e.g. a pupil size), from whichever table has them. Without it, loading keeps only the mapped and recognized fields. A kept fixation column can be used by --color-by, an axis or a hover. Same as keep_columns= in api.load_scanpath_data.
--potec DIR — Load the PoTeC corpus (DiLi-Lab/PoTeC) from DIR, downloading the files it needs (~45 MB) on first use. It has 75 participants, with IDs between 0 and 105 (--list-trials shows them). A trial is one participant reading one text, named <participant>_<text> (e.g. 0_b0). The texts are b0–b5 and p0–p5.
--onestop DIR — Load the OneStop corpus from DIR. The public variant downloads the reports for the chosen regime and parts from OSF on first use, tens to hundreds of MB each. The lacclab variant reads a local export. Choose with --onestop-regime, --onestop-part and --onestop-variant.
--onestop-regime ordinary, information_seeking, repeated, information_seeking_repeated ordinary OneStop reading regime for --onestop (default: ordinary).
--onestop-part Title, Question_Preview, Paragraph, Questions, Answers, QA, Feedback — OneStop trial part for --onestop. Repeatable (default: Paragraph). With several, each part is a separate trial.
--onestop-variant public, lacclab public OneStop source for --onestop: public, downloaded from OSF, or lacclab, a local lab-processed export with no download.
--participant-metadata FILE [FILE ...] — A participant metadata table: one row per participant, with a participant ID column and any other fields. Several files, or a glob, are stacked into one table. Its rows are checked against the loaded participants and reported, and its fields are added to the --list-trials output.
--trial-metadata FILE [FILE ...] — A trial metadata table: one row per trial, with a trial ID column and any other fields. Several files, or a glob, are stacked into one table. It is checked and reported the same way, and its fields are added to the --list-trials output.
--trial-metadata-participant-column
--trial-metadata-reader-column
COLUMN — Key the --trial-metadata table by participant and trial, with this column as the participant ID. Without it, the table is keyed by trial ID alone, and each row applies to every participant's reading of that trial. This is never guessed from the file.
--text-metadata FILE [FILE ...] — A text metadata table: one row per text, with a text ID column and any other fields. Several files, or a glob, are stacked into one table. It is checked and reported the same way, and its fields are added to the --list-trials output. It is keyed by text alone, never by participant.

Fixations

Option Value Default Description
--no-fixations switch — Hide the fixations.
--fixation-index switch — Number the fixations in order (the app's Fixation index).
--no-fixation-index
--no-order
switch — Hide the fixation numbers (the default).
--snap-fixations switch — Move each fixation up or down onto its text line: its word's line, else the nearest. Its x stays. --snap-position sets where on the line.
--snap-position LINES — Where on its line a snapped fixation sits, in line heights from the line's middle: 0 centers it, -0.5 is the top edge, 0.5 the bottom edge (default: -0.5). Used with --snap-fixations.
--palette {default,print,high-contrast} — Color palette (the app's Palette): default (colorblind-safe, Okabe–Ito), print (grayscale, for black-and-white printing) or high-contrast. The app's palette names work too. Each --*-color flag overrides it.
--color-by FIELD — Fixations table column to color the fixations by, e.g. duration_ms, or 'line' for each fixation's text line (same as --color-by-line). Default: '(uniform)', one color, since marker size already shows duration.
--fixation-color COLOR — Fixation color when --color-by is '(uniform)' (default: #0072B2).
--fixation-symbol circle, square, diamond, triangle-up, cross, x, star, hexagon, heart — Fixation marker shape. Unlike color, shape survives a grayscale print (default: circle).
--fixation-colorscale NAME — Color scale for --color-by, e.g. Viridis (default: Blues).
--marker-size-range MIN MAX — Smallest and largest fixation marker size in px, e.g. 4 12 (default: 8 24). A smaller range suits thumbnails.
--marker-size-scale sqrt, linear, log, relative — How duration sets marker size (default: sqrt). sqrt, linear and log map --marker-duration-range onto --marker-size-range, so a duration gets the same size in every trial, comparison and replay. With sqrt, marker area grows with duration. relative stretches each figure from its shortest to its longest fixation.
--marker-duration-range LO HI — The durations in ms that get the smallest and largest marker (default: 50 600). Shorter and longer fixations are clamped to them. Not used by --marker-size-scale relative.
--fixation-opacity O — Fixation marker opacity, 0.1–1.0 (default: 0.7, so overlapping fixations show through).
--fixation-outline-width PX — Outline width around each filled fixation marker, 0–5 px; 0 draws none (default: 0.5).
--fixation-outline-color COLOR — Color of that outline (default: #111111).
--hollow-fixations switch — Draw the fixations as outlines instead of filled markers.
--color-by-line switch — Color each fixation by the text line it lands on, with the lines found from the word boxes. Overrides --color-by. Same as --color-by line.
--fixation-color-range LO HI — Fix the --color-by color scale to LO..HI instead of the trial's range, so several figures share one scale.
--order-font-size PX — Size of the fixation index numbers (default: 10).
--order-font-color COLOR — Color of the fixation index numbers (default: #111111).
--no-fixation-colorbar switch — Leave out --color-by's color bar.
--fixation-colorbar-orientation vertical, horizontal — Fixation color bar: beside the plot (vertical, default) or below it.
--fixation-colorbar-tickangle DEG — Fixation color bar: tick-label angle, -90–90 (default: 0).
--fixation-colorbar-tickfont-size PX — Fixation color bar: tick-label size (default: 12).
--fixation-colorbar-thickness PX — Fixation color bar: thickness, 4–40 px (default: 14).
--fixation-colorbar-length F — Fixation color bar: length as a share of the plot's side, 0.1–1.0 (default: a third of its height upright, 0.6 of its width lying down).

Saccades

Option Value Default Description
--no-saccades switch — Hide the saccades.
--saccade-arrows switch — Draw an arrowhead on each saccade (the app's Direction arrows).
--saccade-color COLOR — Saccade line and arrow color, as hex or a CSS name (default: #CC79A7).
--saccade-style solid, dash, dot, dashdot — Saccade line dash style (default: solid).
--saccade-width PX — Saccade line width in px, 0.5–10 (default: 2).
--saccade-opacity O — Opacity of the saccade lines and arrows, 0.1–1.0 (default: 1). In a comparison, both scanpaths share it.
--saccade-arrow-size PX — Size of the --saccade-arrows arrowheads, 4–40 px (default: 12).
--saccade-color-by-type switch — Color each saccade by its type: forward, skip, refixation, return sweep or regression (the app's By type).
--saccade-color-by-direction switch — Color each saccade as forward or regression (the app's Forward / regression).
--saccade-type-color CLASS=COLOR — Set one saccade type's color, e.g. --saccade-type-color regression=#000000. Repeatable. Types: forward, skip, refixation, return_sweep, regression. Implies --saccade-color-by-type. With --saccade-color-by-direction, it sets the forward and regression colors instead.
--saccade-arcs switch — Draw saccades as upward arcs instead of straight lines (the app's Shape: Arc).

Stimulus

Option Value Default Description
--no-text
--no-labels
switch — Hide the stimulus text.
--highlight-column COLUMN — Boolean Words table column that marks the words to highlight (e.g. is_in_aspan, OneStop's answer span; default: none). --critical-span-style sets how they are drawn.
--critical-span-style mark-text, mark-border, none — How the --highlight-column words are marked: mark-text recolors them, mark-border outlines their boxes, none draws neither (default: mark-text).
--stimulus-image PATH — Draw an image (PNG or JPG) under the scanpath as the stimulus. It is sized to the PNG's pixel size, else to the canvas. Use --stimulus-image-size and --stimulus-image-origin to place a cropped image in fixation coordinates.
--stimulus-image-size WxH — Stimulus image size in px, e.g. 1310x991 (default: the PNG's pixel size, else the canvas). Use with --stimulus-image.
--stimulus-image-origin X,Y — Top-left corner of the stimulus image in screen px, e.g. 305,44 (default: 0,0). Use with --stimulus-image to line a centered crop up with the fixations.
--stimulus-image-opacity O — Stimulus image opacity, 0.1–1.0 (default: 1.0 = opaque). Lower it so the fixations, saccades and word boxes stand out on a busy image.
--show-stimulus-image switch — Draw each trial's stimulus image under the scanpath, from the image_path column of its rows, placed at image_x / image_y. --image-root fills that column, and --sample ships its images. --stimulus-image takes precedence.
--text-color COLOR — Stimulus text color (default: #000000).
--redact-text switch — Draw a rounded block in the text color in place of each word's letters, and leave the words out of the hovers. The figure keeps the text's layout but not its words (the app's Text → Redact).
--highlight-text-color COLOR — Color of the --highlight-column words under --critical-span-style mark-text (default: #D55E00).
--span-border-color COLOR — Box color under --critical-span-style mark-border (default: #000000).
--background-color COLOR — Plot background color (default: #ffffff).
--line-spacing N — Line spacing, in font sizes: the text's font size is the distance between lines ÷ N (default: 3, a blank line above and below).
--no-scale-text-to-boxes switch — Draw the text at --font-size instead of fitting it to the word boxes (the app's Fit to word boxes).
--font-size PX 16 Base figure font size (default: 16).
--font-family NAME — Font for all figure text (default: monospace).

Word boxes

Option Value Default Description
--word-boxes switch — Draw the word boxes.
--no-word-boxes
--no-words
switch — Hide the word boxes (the default).
--word-box-color COLOR — Word-box outline color (default: #6c757d). In a comparison, each scanpath's boxes are outlined in its color instead.
--word-box-line-opacity O — Word-box outline opacity, 0–1; 0 draws the fill only (default: 1). Below 1 the outline color must be #rrggbb, #rgb or rgb(r, g, b).
--word-box-fill-color COLOR — Word-box fill color, drawn at --word-box-fill-opacity: #rrggbb, #rgb or rgb(r, g, b) (default: #646464).
--word-box-fill-opacity O — Word-box fill opacity, 0–1; 0 draws outlines only (default: 0.05).

Heatmap

Option Value Default Description
--heatmap switch — Draw the heatmap.
--no-heatmap switch — Hide the heatmap (the default).
--heatmap-metric COLUMN — What the heatmap colors by (the app's Color → By): the fixation duration column, under your file's name or as duration_ms, or counts for the fixation count. Default: duration_ms.
--heatmap-style word-boxes, smoothed — Heatmap style: word-boxes tints each word box, smoothed blurs the fixations (default: word-boxes).
--heatmap-sigma PX — Blur of --heatmap-style smoothed, as a Gaussian σ in px (default: 2% of the data's larger span, at least 8 px).
--heatmap-colorscale NAME — Heatmap color scale, e.g. Greens (default: Blues).
--heatmap-norm linear, log — Heatmap color scaling: linear (default) or log. Log keeps a few words with long dwell times from washing out the rest.
--heatmap-opacity O — Heatmap opacity, 0.05–1.0 (default: 0.5 for word-boxes, or 0.35 for a trial with no word boxes; 0.45 for smoothed).
--heatmap-range LO HI — Fix the heatmap's color scale to LO..HI instead of the trial's range.
--word-heatmap-col COLUMN — With --heatmap, for a dataset with no fixations: tint each word box by this numeric Words table column, e.g. gpt2_surprisal, instead of its total fixation duration.
--word-heatmap-title TEXT — Color-bar title for --word-heatmap-col (default: Value).
--no-heatmap-colorbar switch — Leave out the heatmap's color bar.
--heatmap-colorbar-orientation vertical, horizontal — Heatmap color bar: beside the plot (vertical, default) or below it.
--heatmap-colorbar-tickangle DEG — Heatmap color bar: tick-label angle, -90–90 (default: 0).
--heatmap-colorbar-tickfont-size PX — Heatmap color bar: tick-label size (default: 12).
--heatmap-colorbar-thickness PX — Heatmap color bar: thickness, 4–40 px (default: 14).
--heatmap-colorbar-length F — Heatmap color bar: length as a share of the plot's side, 0.1–1.0 (default: a third of its height upright, 0.6 of its width lying down).

Raw gaze

Option Value Default Description
--raw-gaze PATH [PATH ...] — The Raw gaze table to draw under the fixations, in the formats --fixations reads and auto-detected the same way. Several paths, or a quoted glob, are stacked into one table. Drawn on static figures and --compare-with comparisons, where each scanpath's samples take its color, but not with --animate. As the only input it is the dataset: its trials are listed and drawn as recorded, and no fixations are detected from the samples.
--no-raw-gaze switch — Load the --raw-gaze table but hide its layer, like turning off the app's Raw gaze switch. With raw gaze as the only input, the figure then shows no gaze.
--sample-raw-gaze switch — With --sample: draw the bundled demo's raw gaze. It is synthesized, and covers one trial only.
--raw-gaze-schema JSON — Column mapping for the --raw-gaze table, replacing auto-detection, in the form --fix-schema takes. Needed only when a column isn't recognized.
--raw-gaze-color COLOR — Raw gaze sample color (default: #888888). In a comparison, each scanpath's samples are drawn in its color instead.
--raw-gaze-marker-size PX — Raw gaze sample size, 1–12 px (default: 4).
--raw-gaze-opacity O — Raw gaze sample opacity, 0.1–1.0 (default: 0.6).

Filters & highlights

Option Value Default Description
--fix-index-range START:END — Draw only fixations START to END, counting from 1, both included, e.g. --fix-index-range 1:40. --animate then replays only that range. With --compare-with it applies to both scanpaths, unless --compare-fix-index-range sets B's.
--fixation-flag SPEC — Highlight or hide one kind of fixation, like the app's Filters & highlights. Repeatable. SPEC is CATEGORY=MODE[,threshold_ms=N][,symbol=S][,color=#RRGGBB]. CATEGORY is short, long, oob (outside every word box) or blink. MODE is off, highlight or hide. threshold_ms applies to short and long only. hide removes the fixations from the figure only; measures and exports keep them. E.g. --fixation-flag short=hide,threshold_ms=80.
--saccade-classes CLASSES — Draw only these saccade types, comma-separated, e.g. --saccade-classes regression,return_sweep. Types: forward, skip, refixation, return_sweep, regression, other (off the text). A hidden type loses its line and its arrow. Default: all.

Figure & canvas

Option Value Default Description
--canvas WxH — Screen size in px, e.g. 2560x1440 (default: 2560x1440 for --sample and --onestop, 1680x1050 for --potec, 1200x800 for --authoring, otherwise estimated from the data).
--coordinate-grid switch — Draw a grid in screen pixels over the scanpath (the app's Axes & grid → Grid).
--coordinate-grid-spacing PX — The grid's major spacing in px. Implies --coordinate-grid. Leave it out for an automatic spacing of 1, 2 or 5 × 10ⁿ px.
--coordinate-grid-font-size PX — Size of the coordinate grid's labels, 6–36 px (default: 18).
--no-plot-frame switch — Leave out the border around the plot area.
--plot-frame-color COLOR — Color of the border around the plot area (default: #000000).
--x-field FIELD — Fixations table column on the x axis (default: x). A non-spatial one draws a chart of the fixations instead of the scanpath.
--y-field FIELD — Fixations table column on the y axis (default: y).
--crop-to-data
--no-full-monitor
switch — Frame the plot on the data instead of the whole --canvas screen (the app's Crop to data).
--crop-margin PX — The margin around the data, in screen px, when cropping to it (default: 5% of the data's extent, at least 20 px). Implies --crop-to-data.

Title & labels

Option Value Default Description
--illustration switch — Apply the app's Illustration design: fixations snapped to their lines, arced saccades, one color for each, and no word boxes, heatmap, fixation index or arrows. A flag you give still wins.
--illustration-label auto, show, hide auto The Illustration label: auto adds it when the figure changes what the data shows (e.g. snapped fixations or arced saccades), show always adds it, and hide leaves it out (default: auto).
--illustration-text TEXT — The Illustration label's text (default: "Illustration · <reasons>").
--title TEXT — A title on the figure. The figure grows to fit it, so the plot keeps its size.
--caption TEXT — A caption on the figure.
--title-size PX — Size of the --title text, 8–48 px (default: 20).
--caption-size PX — Size of the --caption text, 6–36 px (default: 13).
--caption-color COLOR — Color of the --caption text (default: #555555).
--credit switch — A small 'Made with Scanpath Studio' line under the plot. The figure grows to fit it.

Hover

Option Value Default Description
--word-hover-fields FIELDS — Comma-separated Words table columns shown on hover (e.g. text,word_id,gpt2_surprisal).
--fixation-hover-fields FIELDS — Comma-separated Fixations table columns shown on hover (e.g. order_in_trial,duration_ms,eye).
--word-hover-measure FIELD — The reading measure a word's hover shows (default: total_fixation_duration_ms; '' for none).

Legends

Option Value Default Description
--no-highlight-legend switch — Hide the Text highlight legend, which names the highlighted words. The words stay marked. --legend highlight=SPEC places it.
--no-color-legend switch — Hide the Fixation colors legend, which lists the categories of a categorical --color-by and the highlighted fixations. The markers still draw.
--no-saccade-type-legend switch — With --saccade-color-by-type: hide the Saccade types legend. The colored lines still draw.
--legend SPEC — Place one legend. Repeatable. SPEC is KIND=POSITION[,ARRANGEMENT][,SIZE]. KIND is compare (Compare (A/B)), saccades (Saccade types), colors (Fixation colors), size-key (Fixation sizes) or highlight (Text highlight). POSITION is auto, or SPOT-outside or SPOT-inside, with SPOT one of top-left, top-center, top-right, left, right, bottom-left, bottom-center, bottom-right. Outside grows the figure, and left and right run down the side. ARRANGEMENT is stacked or side-by-side, and SIZE the text size in px. E.g. --legend saccades=right-outside,stacked,14. Each legend's switch still decides whether it is drawn.
--no-duration-size-legend switch — Hide the Fixation sizes legend, reference circles labeled in ms. It is drawn when --marker-size-scale is sqrt, linear or log.

Animate

Option Value Default Description
--playback-speed X 1.0 Animation speed multiplier for --animate (default: 1.0 = real time).
--no-autoplay switch — With --animate: start the replay paused. By default the HTML file starts playing when it opens.
--anim-grid-step-ms MS — With --animate: one frame per MS of reading time (default: 100). A smaller step is smoother and makes a larger file.
--anim-max-frames N — With --animate: at most N frames (default: 360). A trial too long for that many at --anim-grid-step-ms gets a wider step.

Size and export

Option Value Default Description
--width PX — Image width in px for PNG, SVG and PDF (default: the figure's size). Use with --height for fixed-size thumbnails.
--height PX — Image height in px for PNG, SVG and PDF (default: the figure's size).
--scale X 2.0 Pixel-density multiplier for PNG, SVG and PDF (default: 2.0).
--width-mm MM — Print width of a PNG in mm, drawn at --dpi (replaces --scale).
--width-in IN — Print width of a PNG in inches, drawn at --dpi.
--dpi N — Resolution of --width-mm / --width-in (default: 300).
--separable-layers switch — Also write one file per layer (word boxes, fixations, saccades, heatmap, labels, stimulus image) to a &lt;output&gt;_layers/ folder, to restyle each in Illustrator or Inkscape. The layers line up when stacked. Static image output only: .svg, .pdf or .png.
--print-code python, cli, both — Print the Python or CLI code that reproduces this figure (python, cli or both), then render as usual. The code sets only the options that differ from the defaults.
--print-code-explicit switch — With --print-code: write every figure option, including the ones at their defaults.

Compare

Option Value Default Description
--compare-with PARTICIPANT:TRIAL — The second scanpath, B, as PARTICIPANT:TRIAL. It comes from the loaded dataset unless --compare-words / --compare-fixations load a second one.
--compare-screen SCREEN_ID — B's screen in a multipart trial, looked up in B's trial (default: its first screen). --screen picks A's. Each scanpath is drawn from one screen.
--compare-layout overlay, side-by-side, stacked overlay How A and B are arranged (default: overlay). Across two datasets, overlay needs canvases of the same size. Different canvases are refused, so use side-by-side or stacked for them. Matching canvases that a dataset did not record still overlay, with a warning.
--compare-stimulus both, a, b both On an overlay, whose word boxes and text to draw (default: both). Two datasets' word boxes line up only when the text is the same.
--label-a TEXT — Name of scanpath A in the legend and hovers. Used by the comparison and by --animate. Needs --label-b.
--label-b TEXT — Name of scanpath B in the legend and hovers. Needs --label-a.
--compare-legend
--no-compare-legend
switch — Draw the Compare (A/B) legend, which names the two scanpaths. On by default; --no-compare-legend hides it. Also applies to --animate.
--style-a SPEC — Style for scanpath A, repeatable: KEY=VALUE[,...]. Colors (#RRGGBB): fix_color, saccade_color, box_color (word-box outline; default fix_color), box_fill_color (default --word-box-fill-color), raw_gaze_color (default fix_color). Also heatmap_colorscale (default --heatmap-colorscale, on the shared range), saccade_style (solid|dash|dot|dashdot), saccade_width (px), marker_size_range (MIN:MAX), opacity (0.1–1), box_line_opacity / box_fill_opacity (0–1; default --word-box-line-opacity / --word-box-fill-opacity), hollow (true|false). E.g. --style-a fix_color=#D55E00,opacity=0.5. --animate uses them too, except box_color, box_fill_color, the box opacities and raw_gaze_color.
--style-b SPEC — Style for scanpath B, repeatable: KEY=VALUE[,...]. Colors (#RRGGBB): fix_color, saccade_color, box_color (word-box outline; default fix_color), box_fill_color (default --word-box-fill-color), raw_gaze_color (default fix_color). Also heatmap_colorscale (default --heatmap-colorscale, on the shared range), saccade_style (solid|dash|dot|dashdot), saccade_width (px), marker_size_range (MIN:MAX), opacity (0.1–1), box_line_opacity / box_fill_opacity (0–1; default --word-box-line-opacity / --word-box-fill-opacity), hollow (true|false). E.g. --style-b fix_color=#D55E00,opacity=0.5. --animate uses them too, except box_color, box_fill_color, the box opacities and raw_gaze_color.
--compare-fixation-flag SPEC — Filters & highlights for scanpath B only. Repeatable. Same SPEC as --fixation-flag, e.g. --compare-fixation-flag short=hide,threshold_ms=80. Replaces --fixation-flag for B.
--compare-saccade-classes CLASSES — The saccade types scanpath B draws, comma-separated, named as in --saccade-classes. Replaces --saccade-classes for B. Not with --animate, which draws every type.
--compare-fix-index-range START:END — Draw only fixations START to END of scanpath B, counting from 1, both included. Replaces --fix-index-range for B.
--stimulus-image-b PATH — Scanpath B's stimulus image, for a side-by-side or stacked comparison across two datasets, where each panel draws its image. Sized and placed like --stimulus-image.
--stimulus-image-size-b WxH — Size of --stimulus-image-b in px (default: the PNG's pixel size, else --compare-canvas, else --canvas).
--stimulus-image-origin-b X,Y — Top-left corner of --stimulus-image-b in B's screen px (default: 0,0).
--compare-words PATH [PATH ...] — The Words table for a second dataset, B's. Same formats and globbing as --words.
--compare-fixations PATH [PATH ...] — The Fixations table for a second dataset, B's. Same formats and globbing as --fixations.
--compare-raw-gaze PATH [PATH ...] — The Raw gaze table for the second dataset, drawn under B's scanpath. Same formats as --raw-gaze. With no second dataset, --raw-gaze already covers both scanpaths.
--compare-dataset-name NAME Dataset B Name of the second dataset, used in the trace names (default: 'Dataset B').
--compare-canvas WxH — The second dataset's screen size in px, e.g. 1680x1050. Estimated from its data when left out. An overlay, or --animate with both scanpaths, checks it against --canvas.

corpus

corpus renders a styled corpus figure from a tidy CSV you already have, as plot_corpus_figure does. For --kind profile the CSV needs word_id and value columns.

scanpath-studio corpus --input profile.csv --kind profile --output profile.svg
Option Value Default Description
--input PATH required The CSV. profile reads word_id and the value column, plus optional lo and hi; distribution reads the value column; difference reads word_id and diff.
--kind profile, distribution, difference required A per-word profile, a distribution, or a difference profile.
-o
--output
PATH required Output file; any extension save_figure writes (.html, .png, .svg, .pdf).
--measure-label MEASURE_LABEL Value Axis and legend label for the value (default: Value).
--series-col SERIES_COL series Column naming the overlaid series, when present (default: series).
--value-col VALUE_COL value The value column (default: value).
--primary-color PRIMARY_COLOR #1f77b4 First series color (default: #1f77b4).
--secondary-color SECONDARY_COLOR #e45756 Second series color (default: #e45756).

check

check runs the Data Management page's Data checks on your tables without opening the app. It looks for:

  • fixations lasting 0 ms or less, or with an infinite duration or onset;
  • fixations and raw gaze samples with no finite position, or one more than a million pixels off the screen;
  • word boxes with no area, or no finite position or size within a million pixels;
  • screen sizes that are not finite and positive.

Each finding gives the rows and trials affected, a few example rows, and what the app does with them. check changes nothing and exits 0 whatever it finds. --json prints the table check_data_health returns.

scanpath-studio check --words ia.csv --fixations fixations.csv
scanpath-studio check --raw-gaze gaze_samples.csv --json
Option Value Default Description
--sample switch — Check the bundled demo instead of your own tables.
--words PATH [PATH ...] — Words table(s), as for render.
--fixations PATH [PATH ...] — Fixations table(s), as for render.
--raw-gaze PATH [PATH ...] — The Raw gaze table, as for render.
--raw-gaze-schema JSON — Column mapping for the --raw-gaze table, replacing auto-detection, in the form --fix-schema takes.
--trial-parts-manifest PATH — JSON manifest assigning source rows to ordered screens.
--json switch — Print the findings as JSON (the rows api.check_data_health returns).
--word-schema JSON — Column mapping for the --words table, replacing auto-detection. A JSON object from each field to a column name, or the path of a JSON file holding one, e.g. '{"trial": "TRIAL_INDEX", "word_id": "IA_ID", ...}'. It is the dict api.load_scanpath_data takes. Needed only when a column isn't recognized, and the error then prints a mapping to start from.
--fix-schema JSON — Column mapping for the --fixations table, replacing auto-detection. A JSON object from each field to a column name, or the path of a JSON file holding one, e.g. '{"trial": "TRIAL_INDEX", "word_id": "IA_ID", ...}'. It is the dict api.load_scanpath_data takes. Needed only when a column isn't recognized, and the error then prints a mapping to start from.
--keep-columns COLUMN [COLUMN ...] — More columns to keep through loading, under the names they have in your files (e.g. a pupil size), from whichever table has them. Without it, loading keeps only the mapped and recognized fields. A kept fixation column can be used by --color-by, an axis or a hover. Same as keep_columns= in api.load_scanpath_data.

cache

A local or desktop run saves your session on your computer, so a refresh or a restart resumes where you left off. It saves uploaded datasets, column mappings, view settings, saved designs, metadata tables and annotations. cache shows what is stored and can delete it.

scanpath-studio cache            # datasets, rows, size, folder, last written
scanpath-studio cache --path     # just the folder
scanpath-studio cache --json     # the same status as JSON
scanpath-studio cache --clear    # delete the recovery cache
Option Value Default Description
--path switch — Print the cache folder and exit.
--json switch — Print the status as JSON.
--clear switch — Delete the recovery cache.

The same information is at the foot of the Data Management page, under Saved on this computer. A running app writes a new copy at its next change, so clear the cache with the app closed.

To Use
turn caching off for one launch scanpath-studio --no-persist
turn it off wherever the variable is set SCANPATH_STUDIO_PERSIST=0
move the folder SCANPATH_STUDIO_STATE_DIR

Hosted deployments do not cache by default.

version

version says which build this is and how it was installed. --check also asks GitHub whether a newer release is out and says how to update your install. Only --check uses the network.

scanpath-studio version           # the build, and how it was installed
scanpath-studio version --check   # …and whether a newer release is out
Option Value Default Description
--check switch — Ask GitHub for the latest release and say how to update this install.
--timeout SECONDS 5.0 How long to wait for GitHub, in seconds (default: 5).

Between releases the version names the build: 0.35.0.post3+g8f18219 is three commits after 0.35.0, at commit 8f18219. The same check is Help → About → Check for updates in the app, and check_for_updates in Python.

cite

cite prints how to cite Scanpath Studio. --corpus adds the citation of the public corpus you used.

scanpath-studio cite                           # BibTeX
scanpath-studio cite --format apa --corpus onestop
scanpath-studio cite --format credit           # one sentence for a figure caption
Option Value Default Description
--format bibtex, apa, ris, csl-json, credit bibtex Bibtex (default), apa, ris (Zotero, Mendeley, EndNote), csl-json, or credit: one sentence to paste into a figure caption.
--corpus onestop, potec — Add this public corpus's citation after the software's.

You don't have to add the citation to your files by hand: every figure render writes carries it in its file metadata. The same entries are cite in Python.