Skip to content

v0.23.0

Choose a tag to compare

@github-actions github-actions released this 24 Jun 09:01

Added

  • Stimulus-font install hint — when a dataset declares its typeface
    (MultiplEYE), a note under Text font names the font, links a download, and
    gives per-OS install steps. The overlaid labels only match the stimulus image
    pixel-for-pixel when that exact font is installed (the browser otherwise falls
    back per script, so a CJK font's half-width Latin — URLs/digits — drifts); the
    note also points to the stimulus image as the reliable fallback.
  • Corpus Analysis — question-oriented analysis sections (AN-1…28) — the single
    Aggregated Views subtab is replaced by four sections, each answering one
    question, plus the WIP Generations tab:
    • Per text (one text, many readers): stacked per-reader word profiles with an
      optional cohort-mean overlay, a word × reader heatmap, the cohort word profile
      with a spread band, word difficulty tinted on the true-to-scale stimulus, a
      per-word measure-vs-linguistic-feature scatter (surprisal / frequency / length /
      POS) with a trend line, and skip / regression-in rates per word.
    • Per reader (one reader, many trials): measure distribution vs the cohort
      (violin/box), a reading-speed summary card with cohort percentiles, fixation
      duration over time, the saccade-amplitude × fixation-duration density scatter,
      progressive vs regressive saccades per trial, the landing-position (PVL) curve,
      and this reader's per-trial trend.
    • Per group (a cohort): pooled distributions, the group word profile, a
      per-reader summary table, and the group trend (optionally with per-reader lines).
    • Group comparison (two cohorts): overlaid distributions, the per-word A−B
      difference profile (diverging colormap + zero line), paired summary bars with
      error bars, an effect size + significance test (Cohen's d, Welch t-test /
      Mann–Whitney; exploratory), and a stacked two-group word heatmap.
    • Cross-cutting controls every section reads: a shared measure picker
      (TFD/FFD/FPRT/RPD/n_fixations/skip/regression-in/out + fixation duration /
      saccade amplitude), mean/median/sum aggregation and SD/SEM/IQR/bootstrap-CI
      spread, a z-score within reader normalization toggle, a min-readers/min-trials
      guard, and a per-view tidy-table CSV download. Groups are defined either by
      splitting a categorical field or by two independent filter sets. The per-text
      stimulus view now honours the active global_* visualization settings instead
      of hard-coded display options (AN-28). Adds scipy for the group tests.
  • Saccade line width — a width slider (0.5–10 px, default 2) in the Saccade-style
    popover, threaded through every plot, bulk export, save/restore, and deep links
    (per-scanpath in comparisons); plus headless --saccade-color/--saccade-style/
    --saccade-width CLI flags and a plot_scanpath(saccade_width=…) kwarg.
  • Show full monitor toggle — frame the plot to the whole presentation monitor
    instead of cropping to the data extent (single, animated, comparison, bulk export).
  • MultiplEYE corpus supportload_multipleye(), the in-app Public datasets
    picker, and the Add dataset wizard (browser upload) load the multilingual
    reading corpus (identity parsed from folder/file names, one trial per stimulus
    page, character AOIs aggregated to word boxes), with its comprehension questions,
    pre-aggregated reading measures (IA_*), reader metadata, and a true-to-scale
    stimulus-page background image.
  • OneStop public dataset — the Public datasets picker now offers the
    OneStop 360-participant
    English corpus, downloading the paragraph-level interest-area + fixation
    reports from OSF on demand (regime-selectable:
    ordinary / information seeking / repeated / information-seeking-repeated),
    rendered true-to-scale on OneStop's 2560×1440 monitor. Distinct from the
    env-var $ONESTOP_DATA_DIR server bundle. See docs.
  • Public datasets (PoTeC + MultiplEYE) shown by default (SCANPATH_PUBLIC_DATASETS=0
    to hide). Schema auto-detection now recognizes MultiplEYE columns.
  • MultiplEYE server-bundle source — a URL-addressable multipleye data
    source (?source=multipleye) for deep-linking a review app straight into the
    viewer at a given participant + trial. Gated on $MULTIPLEYE_DATA_DIR pointing
    at a raw export root, it reuses the native MultiplEYE loader (same raw frames,
    schema auto-detection, and authoritative 1920×1080 monitor) as the public
    source — so it renders identically — and fast-paths to a single session for
    ?participant (resolved case-insensitively). Exposed on every surface: the
    sidebar source list, the Share/deep-link round-trip, and headless
    render --source multipleye [--export DIR]. Mirrors the OneStop server
    bundle.
  • Upload-wizard helpers — derive trial/participant ids from the filename
    (delimiter split or regex) and aggregate character AOIs into word boxes.
  • Fixation classification (visual only) — under the Fixation controls, flag
    short / long / out-of-bounds fixations and either highlight them (chosen
    marker + colour) or discard them from the plot, with editable short/long
    duration thresholds. Affects only what's drawn — measures and exports are
    unchanged. Replaces the old out-of-text marker toggle.
  • Drag-to-reorder trial chips — an inline ✏️ Edit chips popover beside the
    chip strip (replaces the sidebar picker): drag fields between Shown and
    Available and reorder within Shown. The chip strip's More dropdown now
    holds the full chip list (so any chip clipped at the line edge is always
    reachable) alongside the summary stats.
  • Column mapping surfaces auto-detected columns per field (and flags when
    you've overridden the detected default).
  • Fixation marker opacity — an opacity slider (global + per-scanpath, default
    0.7) replaces the Hollow circles toggle, so overlapping fixations show through;
    threaded through every plot, animation, comparison, bulk export, save/restore and
    deep links.
  • Fixation-index window on the main plot — a range slider in the Fixation popover
    draws only fixations (and their saccades) within the chosen order_in_trial range,
    applied to the single, animated and comparison views; chips/panels keep the full trial.

Changed

  • Public-datasets picker reworked (DATA-4…7) — the corpus list is now a
    searchable selectbox (shows each corpus' short name + a language · size
    caption, one-line description, and home link) that scales as more datasets are
    added; local/private upload stays the primary path. Each loader now shows
    an Expected files layout for its data directory and a found vs. Download
    status — a one-click ⬇ Download (PoTeC, OneStop) replaces the always-on
    Download if missing checkbox, so an already-downloaded corpus never re-checks
    the network. The per-source participant/text narrowing (PoTeC Texts/Readers,
    MultiplEYE Sessions/Stimuli) is gone — each source loads the whole corpus and
    the global Narrow by trial filters scope it. (The headless load_potec /
    load_multipleye keep their readers/texts/sessions/stimuli args.)
  • Internal: split app.py (4087 → ~1640 lines) into focused modules —
    deep-link/share/config → url_state.py, the upload wizard → wizard.py — and
    factored plot overlay layers into helpers. No behavior change.
  • Navigation streamlined — Corpus Analysis is a header toggle; Data Inspection
    and Share are Scanpath subtabs; the sidebar view-nav is gone.
  • Trial selection reworked into Filter → Pick — Text/Participant/condition
    filters narrow the pool, then one row picks the trial (dropdown + scrubbing
    slider + ◀ ▶); Browse-by modes removed.
  • Comparison styling moved into the per-layer Fixation/Saccade popovers, beside
    the single-trial controls.
  • Compare mode reworked. The second-trial selector sits above the chips and
    mirrors the main picker — trial id + ★ same-text / 👤 same-participant
    markers in the dropdown (ordered stars → same-participant → rest), index/N · id
    slider, ◀ ▶. The overlay/layout + show-A/B-legend config moved into a rail
    ⚙️ Compare popover; the A/B legend (static and animated overlay) is
    optional and hidden by default; the figure title is removed; each chip strip's
    trial id is coloured to its scanpath (replacing the A/B legend line). Color
    fixations by
    now works in compare too — it colours both scanpaths by the metric
    (shared scale), with the per-scanpath flat colour as the A/B marker outline; the
    redundant global saccade controls stay hidden.
  • Welcome tour walks the whole Scanpath screen in reading order (plot →
    selection → chips → rail → panels → sidebar); the redundant Exit button is
    gone (the ✕ closes it).
  • Styling & chrome polish — saccade arrows off by default, span-border colour,
    horizontal/rotatable colour bars, tighter control rail, less heading clutter,
    a dismiss ✕ on the welcome tour.

Fixed

  • MultiplEYE reading text now aligns with the stimulus image (BUG-3). The
    loader reads the real FONT_SIZE + font from the stimulus config and stamps
    them onto the data (stimulus_font_px / stimulus_font_family); on a dataset
    switch the app snaps its font controls to the exact size and CJK typeface (and
    off "scale text to boxes", since the precise px is known), so the word labels
    land on the printed text instead of being inferred ~3× too small in a generic
    font. The scale-text-to-boxes path also improved: the font is budgeted from
    the line pitch (not the glyph-tight box height) and the box-width cap is
    script-aware (full-width CJK vs half-width Latin, per word), so CJK corpora and
    mixed CJK+Latin lines size sensibly. OneStop sizing is unchanged.
  • Compare-mode fixations no longer turn black. The per-scanpath colour pickers
    (rendered only when Compare is on) desynced to black and committed that on the
    next interaction; they now pass an explicit value and a falsy colour can't leak.
  • Trial filter resets on a dataset switch (and is restored per-dataset when you
    switch back), so a stale filter can't silently apply to a different corpus.
  • Clearer image-export errors when Chrome is missing — point to
    kaleido_get_chrome / the browser-free HTML export, with a pre-flight check and
    a warm→cold render fallback for the animation export.
  • Stimulus image now shows in Animate mode (was static-only).
  • Switching public datasets re-detects the column mapping and snaps the canvas to
    that corpus' monitor
    — fixes MultiplEYE pages collapsing into one trial and
    off-scale rendering.
  • Heatmap colour matches the picker (default now blue; style uses a radio).
  • Save & restore captures every setting — colour-bar orientation/ticks,
    fixation classification, span-border colour, and per-scanpath comparison styling.
  • Chips stay on one line when space is tight.

Install/upgrade: pip install -U scanpath-studio