Commit Graph

46 Commits

Author SHA1 Message Date
Michael Pilosov
56279dbb1b runs: server-side chip filter via Prefect tags + cassette chip UX
- New runs are tagged on dispatch with dataset:<id> / algorithm:<short> /
  N:<n> / T:<t> / J:<j> (single value per axis).
- /runs accepts ?dataset=&algorithm=&N=&T=&J= and applies Prefect's
  tags: {all_: [...]} server-side. Without filter, fetch cap is 10; with
  filter, 50 so narrow results aren't truncated. Prefect's own 200-limit
  on filter queries is clamped inside recent_runs.
- New /runs/axes.json returns the universe of chip values across the last
  200 deployment runs so the chip bar shows history even when the current
  slice is narrow.
- runs-filter.js rewritten to cassette-style single-select: clicking the
  selected chip releases it. No 'all'/'none' meta chips. Chip state feeds
  #runs-slot via hx-vals; a filter-changed custom event triggers an
  immediate refetch on change, in addition to the 3s poll.
- Prefect client gets an update_tags(run_id, tags) helper.
- scripts/backfill_tags.py PATCHes tags onto every existing deployment
  run (dry-run by default, --apply to commit).
2026-04-22 17:48:35 -06:00
Michael Pilosov
aa1303e373 runs filter: add J (jitter) chip group alongside N and T 2026-04-22 17:28:55 -06:00
Michael Pilosov
4ecdc7f586 modal: hide axes dropdown for single-panel runs
Disable #cc-sync in panel-grid when there's only one stem (nothing to
sync; aspect is fixed by the dialog) and hide any .compare-controls
label whose select is disabled via :has.
2026-04-22 17:23:51 -06:00
Michael Pilosov
d70eff3704 runs filter: N + T chip rows; group all/none meta chips; explicit row layout
- Add N and T axes alongside dataset/algorithm; chips populated from runs
  in the list, axis group hidden when there's a single unique value.
- Dataset+algorithm on row 1, N+T on row 2 via two explicit
  .runs-filter-row flex containers (cleaner than a sentinel break elem
  that double-counted the row-gap).
- 'all' and 'none' meta-chips now wrap as a unit inside .chip-meta-wrap
  so one doesn't orphan to the next line.
- Row is hidden entirely when every axis in it collapses to a single
  value (:has selector on .runs-filter-row).
2026-04-22 17:20:08 -06:00
Michael Pilosov
bdbebaa7e8 compare: click to pin a point's highlight; hover temporarily overrides
Click a point in any panel to pin its id — highlight persists after the
cursor leaves, across all linked panels. Click the same pinned point (or
empty space) to unpin. Hover still shows the point under the cursor,
briefly overriding the pinned display. Canvas cursor is now crosshair to
hint at the interaction.
2026-04-22 17:00:29 -06:00
Michael Pilosov
a4fc36352d compare: axes dropdown combines sync (scaled/locked) × aspect (1:1/3:2)
Canvas height now derives from column width via aspect-ratio (CSS custom
prop --canvas-aspect set by JS on the grid host), with --panel-h as a
ceiling. Dropdown options: scaled/locked × 1:1/3:2. Default scaled 3:2.
Legacy 'independent'/'locked' values still parse. Canvas resizes after
aspect changes via requestAnimationFrame.
2026-04-22 16:57:15 -06:00
Michael Pilosov
9b178dad38 runs: filter chips + compare selection up to 8
- /compare accepts ?stem=…&stem=… (repeated) for 2-8 runs; legacy ?a=&b=
  still works. compare.js parses multi-stem; template drops stem_a/_b
  data attrs that were unused.
- compare-select.js: MAX bumped to 8, button enables at 2-8 selected.
  URL emitted as ?stem=… per selection.
- runs list gets a dataset/algorithm chip filter bar above #runs-slot
  (pattern ported from metrics.js). Chips reflect the union of values in
  the current list; selection state persists across htmx swaps. Non-
  matching rows get .filtered-out (display:none).
- _runs.html li now carries data-embedder/data-generator so the filter
  can key on them.
2026-04-22 16:41:06 -06:00
Michael Pilosov
44de8deeeb viz: extract N-panel-agnostic module; homepage modal reuses it for single-run view
- panel-grid.js (new): exports mountPanels({host, controls, stems}) → {destroy}.
  Moved createPanel + shared control wiring + linked-hover + pad-to-match
  time mapping out of compare.js. Stem-count-agnostic; works for 1, 2, or N.
- Panel DOM is cloned from <template id=compare-panel-tpl> on each page.
- compare.js is now a ~10-line shim: parse ?a=&b=, call mountPanels.
- Per-panel color is viridis-sampled by index/N (middle viridis for N=1,
  ends-of-palette for N=2, linear lerp for N≤8, cycle at N≥9). Set as
  --panel-color on the panel element; CSS reads it for tag/time-seg.
- Homepage <dialog id=run-modal> + run-modal.js hijack the 'embedding' link
  (plain click → modal; meta/ctrl/middle-click still opens plotly HTML).
  Dialog close disposes every panel's renderer/geometry/material.
- .compare-grid → repeat(auto-fit, minmax(360px, 1fr)) handles N=1..many,
  replaces the <900px one-column media rule.
- Runs list: relabel Prefect's 'Late' state as 'Queued' — more honest
  description of what the runner is doing at the concurrency cap.
2026-04-22 16:17:01 -06:00
Michael Pilosov
a5614ac371 runs list: mark older runs with duplicate-stem output as stale, hide their compare checkbox
When two runs share identical params they write to the same figs/<stem>.html,
and the most recent overwrites the earlier. Previously both got a compare
checkbox with the same data-stem, so toggling one toggled both via the JS
Set. Now we flag older duplicates server-side (first occurrence wins — Prefect
returns runs START_TIME_DESC), drop their checkbox, fade the row, and mark
'overwritten' on the outputs line.
2026-04-22 15:35:05 -06:00
Michael Pilosov
fc1ae9dbc9 compare: default color mode to 'original' 2026-04-22 15:30:50 -06:00
Michael Pilosov
9277229024 compare: color points by their original-dataset label (mono|original toggle)
Server enrichment regenerates the dataset deterministically (random_state=0,
matching the flow's _DEFAULT_GENERATOR_KWARGS — the stem's seed drives jitter,
not generation) and attaches per-point labels + label_kind to frames.json.

Client picks the dataset-picker's scheme: continuous ramp for s_curve/swiss_roll,
8-color categorical palette for blobs/gaussian_quantiles/classification. Jitter-
added points (id >= num_points) render black. Rainbow material is opaque with
alpha cutoff so overlapping points don't blend to the ramp midpoint.

Swiss_roll and swiss_roll_hole collide on generator_path; the plain variant
wins for now (kwargs aren't preserved through the flow's metrics.json).

Bumped Cache-Control on the frames endpoint so browsers don't cache stale
pre-enrichment payloads.
2026-04-22 15:29:03 -06:00
Michael Pilosov
d3f5088233 compare: pad-to-match time mapping + fix stalled play at small du
- applyU now maps u to a shared global frame index uGlobal in [0, maxT-1];
  each panel clamps to its own (T-1), so a shorter timeline pads its last
  frame while the longer one finishes — both advance at the same wall-clock
  tempo instead of rescaling their timelines.
- tick() keeps u as a float closure variable; reading it back from the
  integer-step scrubber was quantizing du to 0 at slow tempo + high T
  (1600ms/frame, T=24: du ≈ 4e-4 → round to 0 on scrub), stalling playback
  after one frame.
2026-04-22 14:44:08 -06:00
Michael Pilosov
89401e3aee compare: extend mismatch highlighting to embedder and generator slugs 2026-04-22 14:38:36 -06:00
Michael Pilosov
41ce5ee88a compare: highlight mismatched N/T/J/s params in red between the two panels 2026-04-22 14:37:04 -06:00
Michael Pilosov
c9868ff83e compare: wrap N/T/J/seed params onto its own line in each panel header 2026-04-22 14:35:24 -06:00
Michael Pilosov
dd01638110 compare: replace stem-link filename text with a new-tab arrow glyph 2026-04-22 14:33:18 -06:00
Michael Pilosov
8bc8b801dc compare: move control bar above the panels 2026-04-22 14:32:32 -06:00
Michael Pilosov
a976ba893a compare: slow base playback 4x (1x = 1600ms/frame, was 400ms) 2026-04-22 14:31:20 -06:00
Michael Pilosov
d0b026734a compare: interpolate between frames for smooth point-trajectory motion
Default is smooth (lerp each point between adjacent frames); a motion:step
toggle preserves the snap-to-frame behaviour. Points missing in either
adjacent frame are hidden during the transition to avoid pop-in.
2026-04-22 14:29:24 -06:00
Michael Pilosov
fc6aad5516 compare: side-by-side three.js animation with linked scrub, hover, and theme
- /compare page renders two ortho-camera panels fed by /api/runs/{stem}/frames.json
- shared controls: play/pause, scrubber, speed (0.5-4x), axes sync (independent/locked)
- linked hover: picks nearest point in one panel, highlights matching point_id in other
- add/remove-jitter nulls handled via per-frame packed positions + setDrawRange
- independent error states per panel; theme-aware colors via themechange event
2026-04-22 14:26:45 -06:00
Michael Pilosov
e680867f8b compare: selection UX on runs list + /compare placeholder page
- per-run checkbox when embedding HTML exists; cap at 2 selected
- sticky 'compare selected' button opens /compare?a=&b= in new tab
- selection state persists across the 3s htmx poll via a Set keyed by stem
- /compare stub validates stems, renders scaffolding (three.js UI next)
2026-04-22 14:19:26 -06:00
Michael Pilosov
acb596743a reducer list: right-align pkg column so wrapped class-path lines stay on the right 2026-04-22 13:58:01 -06:00
Michael Pilosov
4ee78dd466 reducer list: break long class paths on '.' so they wrap cleanly on narrow (non-mobile) viewports 2026-04-22 11:48:52 -06:00
Michael Pilosov
97ee3d4db6 reducer list: blurb spans full width on narrow viewports 2026-04-22 11:34:24 -06:00
Michael Pilosov
f524dcce51 clean up / clarify labels 2026-04-22 11:30:52 -06:00
Michael Pilosov
b108204289 fix min height 2026-04-22 11:25:30 -06:00
Michael Pilosov
8db92089a1 theme toggle: absolute (not fixed) so it doesn't follow scroll 2026-04-22 11:16:20 -06:00
Michael Pilosov
f07fa567d0 anchor theme toggle to top-right of viewport 2026-04-22 11:14:16 -06:00
Michael Pilosov
7039b39d9d nowrap nav link and accordion toggles on small viewports 2026-04-22 11:13:03 -06:00
Michael Pilosov
2e76cda332 page titles: drop web1 and em-dashes 2026-04-22 11:10:41 -06:00
Michael Pilosov
03309e28a6 move prefect badge from masthead to footer 2026-04-22 11:09:44 -06:00
Michael Pilosov
8bb186269b header: 'deployment' -> 'ver' 2026-04-22 11:08:14 -06:00
Michael Pilosov
5ce69f2ef0 inline metrics into home page; footer copyright; drop prefect-api URL
Migrates the metrics view from a separate /metrics page into an inline
§ 5 collapsible section on the home page (swept in from pre-existing
unstaged edits). Also updates the footer to © 2026 Mind the Math LLC
and drops the prefect-api URL from both mastheads.
2026-04-22 11:08:14 -06:00
Michael Pilosov
86e11a6a11 restyle sec 0 + incl fig 2026-04-22 10:57:24 -06:00
Michael Pilosov
bb46e5a18d add §0 introduction (default collapsed)
Three short paragraphs framing what the notebook studies: stability of
2-D embeddings under controlled perturbation of the input over time,
the two metrics logged per run, and why the streaming/longitudinal
angle matters for both visualization and downstream classification.
2026-04-22 10:41:24 -06:00
Michael Pilosov
158f3fdefa theme picker canvas backgrounds
Read --picker-panel from the card's computed style at scene creation
and re-apply on themechange, so the three-js canvases flip with the
rest of the UI instead of staying stuck on the light palette.
2026-04-21 21:56:14 -06:00
Michael Pilosov
d385337a36 require dataset selection before submit
Client-side: disable the form submit button until the picker writes a
dataset_id. Server-side: reject posts where dataset_id is present but
empty, instead of silently defaulting to make_s_curve.
2026-04-21 21:54:50 -06:00
Michael Pilosov
61e9221b3a dark/light theme toggle 2026-04-21 21:51:16 -06:00
Michael Pilosov
ca59516f26 multiselect chips for dataset/algo filters 2026-04-21 21:07:33 -06:00
Michael Pilosov
b2be3d0835 metrics page with svg plots and filters 2026-04-21 21:02:58 -06:00
Michael Pilosov
c6bd693058 runtime display 2026-04-21 20:22:38 -06:00
Michael Pilosov
b99a8e3287 num snapshots fallback in frontend recent runs 2026-04-21 20:08:10 -06:00
Michael Pilosov
eaeb6b5c2a styling changes (radio for N) 2026-04-21 20:07:42 -06:00
Michael Pilosov
92069a3c91 rename snapshots -> timesteps 2026-04-21 19:55:01 -06:00
Michael Pilosov
afc9b5b2f2 migrate new data picker 2026-04-21 19:46:31 -06:00
Michael Pilosov
ca0ad9fd2d rename folder 2026-04-21 19:30:45 -06:00