/ concept-collection / hitandrun-interactive
Sign in
concept-collection / hitandrun-interactive
hitandrun-interactive / CLAUDE.md
159 lines · 7.7 KBCodeBlameHistory
3Tips for future agents working in this repo. Patterned after the sibling
4`surfacefun-interactive` project (same numbl + uihtml two-way bridge), but the
5figure is a 2D canvas instead of a three.js surface.
7## Architecture
9- `app/` — React single-file widget (`npm run build``app/dist/index.html`)
10- `*.m` at root — scripts users open and run in [numbl](https://numbl.org)
d9d003fAdd non-convex (star) regions with a general hit-and-run samplerJeremy Magland 11- `helpers/` — the region/sampling algorithm (`make_region`, `hit_and_run`,
12 `hit_and_run_general`), put on the path by the driver via `addpath('helpers')`
13- `numbl-project.json` — project metadata; `entry` is the landing page. Its
14 `figures` array declares the editor-less figure view the deploy exposes at
15 `#figure/sampler` (runs `hitandrun_demo.m`, shows just the interactive figure);
16 the org profile's "live" link points there.
18### Multi-file layout / addpath
20`hitandrun_demo.m` is the **driver**; its first statement is
21`addpath('helpers')` so `make_region` / `hit_and_run` resolve from the subdir.
22Two constraints make that placement mandatory:
24- `addpath(<literal>)` must be a **leading** statement in the driver, before any
25 other non-comment statement (numbl's static path resolution requires it; the
26 runtime/interpreter path is fine with it too). It also cannot live inside a
27 function file — only the driver. So `hitandrun_sampler.m` can't add the path
28 itself; run `hitandrun_demo.m`, not the sampler directly.
29- Plain subdirectories are otherwise invisible to function resolution — only
30 `addpath`'d dirs (plus root, `+pkg`, `@Class`, `private/`) are searched.
32This works the same in the browser deploy (the worker runs the interpreter,
33which honors the runtime `addpath`).
35## Data flow
37**MATLAB → figure:** set `uihtml(..., 'Data', struct)` or call
38`sendEventToHTMLSource(src, 'eventName', data)`
40**Figure → MATLAB:** call `sendToMATLAB('eventName', value)` (see `bridge.ts`);
41receive via `HTMLEventReceivedFcn`
43## The demo, built in stages (all done)
451. **(done)** Generate a convex region + `N` hit-and-run samples in the script;
46 show region + samples in the figure. The samples are drawn server-side and
47 sent via `Data`.
482. **(done)** Add controls to the figure panel: a **Samples** slider, a
49 **Resample** button, and a **New region** button.
503. **(done)** Wire those controls to the sampler (two-way bridge).
d9d003fAdd non-convex (star) regions with a general hit-and-run samplerJeremy Magland 514. **(done)** Non-convex regions. A **non-convex region** checkbox switches to a
76fb400Non-convex region: replace star polygon with a two-bulb dumbbellJeremy Magland 52 dumbbell — two convex bulbs joined by a narrow tube (`make_region(false)`),
53 sampled by `hit_and_run_general`; the movie draws the multiple in-region
54 segments a line makes through it. The dumbbell is non-star-shaped and need not
55 contain the origin, so the general sampler seeds itself with an interior point
56 found by rejection.
a50c671Non-convex: add local-segment vs. union sampling modeJeremy Magland 575. **(done)** Local vs. union sampling. A **local segment only** checkbox (shown
58 only when non-convex) switches `hit_and_run_general` between sampling the
59 union of all in-region segments (default; uniform) and only the segment
60 through the current point (local; non-uniform). It drives both the sampler
61 and the movie overlay (`regionSegments`'s `localOnly`).
63The figure → script protocol (each request carries `convex`, plus `local` for
64non-convex regions):
66- **Samples** slider (on release) / **Resample** / **local** toggle →
67 `sendToMATLAB('resample', { n, x, y, convex, local })`. `x, y` are the
68 *current region's* vertices — the script is **stateless**, so it samples the
69 region it is given and replies with `sendEventToHTMLSource(src, 'samples', {
70 x, y, n })`.
d9d003fAdd non-convex (star) regions with a general hit-and-run samplerJeremy Magland 71- **New region** / **non-convex** toggle → `sendToMATLAB('newRegion', { n,
a50c671Non-convex: add local-segment vs. union sampling modeJeremy Magland 72 convex, local })`. The script builds a new region of that type and replies with
73 a full `sendEventToHTMLSource(src, 'data', <payload>)` (same shape as the
74 initial `Data`, plus `convex`).
a50c671Non-convex: add local-segment vs. union sampling modeJeremy Magland 76`hitandrun_sampler.m`'s `sample_region(vx, vy, n, convex, local)` dispatches to
77`hit_and_run` (convex, JIT) or `hit_and_run_general(..., local)` (non-convex,
78interpreter). The non-convex path can't JIT (sort + point-in-polygon), so
79`App.tsx` caps its `N` lower via `SAMPLE_CHOICES_NONCONVEX`. `local` only applies
80to non-convex regions (`App.tsx`: `useLocal = nonConvex && local`); toggling it
81resamples the same region.
a50c671Non-convex: add local-segment vs. union sampling modeJeremy Magland 83Ideas for the next iteration: show the chain path / burn-in, or animate the
84walk.
86## Client-side vs. server-side interactivity
88- **Low-latency / view-only** (e.g. dot size, zoom): update React state only —
89 instant, no MATLAB round-trip.
90- **New samples** (depends on the RNG and the algorithm): `sendToMATLAB`
91 script re-runs → `sendEventToHTMLSource` → React re-renders.
93## Key files
95| File | Purpose |
96|------|---------|
a50c671Non-convex: add local-segment vs. union sampling modeJeremy Magland 97| `app/src/App.tsx` | Main React component; reads data, hosts the panel, non-convex + local toggles, movie `regionSegments` |
d9d003fAdd non-convex (star) regions with a general hit-and-run samplerJeremy Magland 98| `app/src/render/RegionView.tsx` | 2D canvas renderer (region outline + sample dots + movie `segments`) |
9fbdc3eInteractive hit-and-run sampling of a 2D convex regionJeremy Magland 99| `app/src/bridge.ts` | `onData` / `onHostEvent` / `sendToMATLAB` helpers (generic; identical across these projects) |
d9d003fAdd non-convex (star) regions with a general hit-and-run samplerJeremy Magland 100| `hitandrun_sampler.m` | Opens the figure, sends data, handles `resample`/`newRegion` (figure plumbing: `on_event`, `sample_region`, `pack_data`, `pack_samples`) |
76fb400Non-convex region: replace star polygon with a two-bulb dumbbellJeremy Magland 101| `helpers/make_region.m` | Random region — convex polygon on an ellipse (no convhull, so the auto-running figure view doesn't race the qhull backend load), or `make_region(false)` for a dumbbell (two disks + narrow tube) |
d9d003fAdd non-convex (star) regions with a general hit-and-run samplerJeremy Magland 102| `helpers/hit_and_run.m` | Convex hit-and-run sampler (half-plane chord intersection; JIT) |
a50c671Non-convex: add local-segment vs. union sampling modeJeremy Magland 103| `helpers/hit_and_run_general.m` | Non-convex hit-and-run sampler (union of all in-region segments, or `local` = only the one through the current point; interpreter) |
9fbdc3eInteractive hit-and-run sampling of a 2D convex regionJeremy Magland 104| `hitandrun_demo.m` | User-facing driver: `addpath('helpers')` + seed + call the sampler |
106## Local iteration
108Always rebuild the figure app first — both workflows read the prebuilt
109`app/dist/index.html`:
111```
112cd app && npm install && npm run build # produces app/dist/index.html
113cd ..
114```
116`NUMBL` below is a local clone of https://github.com/flatironinstitute/numbl
117(e.g. `~/src/numbl`). Run its CLI with `npx tsx $NUMBL/src/cli.ts …` — no
118global install.
120### A. Quick run via the CLI (fastest inner loop)
122```
123npx tsx $NUMBL/src/cli.ts run hitandrun_demo.m --plot
124```
126`--plot` opens the figure in a browser and keeps the script's session alive so
127figure → script callbacks work (Ctrl+C to stop). Good for iterating on the `.m`
128+ app together.
130### B. Preview the actual GitHub Pages site locally
132This reproduces what the [deploy workflow](.github/workflows/deploy.yml) ships
133(it calls `flatironinstitute/numbl/.github/actions/build-site@main`, which is
134just `cli.ts build-site` after building the site-viewer). The numbl in the
135deployed site runs the `.m` in a **web worker in the browser**, and it keeps a
136live uihtml session there — so figure → script callbacks (`resample`) round-trip
137in the deployed site exactly like in the CLI `--plot` path. (That two-way bridge
138is why the workflow builds numbl from `main` rather than the npm release.)
140```
141# one-time, in the numbl clone: build the browser site-viewer
142( cd $NUMBL && npm ci && npm run build:site-viewer )
144# from this project: bundle project + viewer into _site/
145npx tsx $NUMBL/src/cli.ts build-site . --out _site --base /
147# serve it (localhost is a secure context, so coi-serviceworker.js can set the
148# COOP/COEP headers numbl's WASM needs)
149( cd _site && python3 -m http.server 8080 )
150# → open http://localhost:8080/
151```
153Notes:
154- `--base /` is for serving at localhost root. GitHub Pages serves this project
155 at `/<repo>/`, so the workflow auto-detects `--base /hitandrun-interactive/`.
156 Content is identical; only asset paths differ.
157- `_site/` and `dist/` are git-ignored (see `.gitignore`).
158- The real target is GitHub Pages, where the same single-file app runs against
159 numbl compiled in the browser.
moveopenescclose