/ concept-collection / hitandrun-interactive
Sign in
concept-collection / hitandrun-interactive
hitandrun-interactive / CLAUDE.md
135 lines · 5.9 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)
11- `helpers/` — the region/sampling algorithm (`make_region`, `hit_and_run`),
12 put on the path by the driver via `addpath('helpers')`
13- `numbl-project.json` — project metadata; `entry` is the landing page
15### Multi-file layout / addpath
17`hitandrun_demo.m` is the **driver**; its first statement is
18`addpath('helpers')` so `make_region` / `hit_and_run` resolve from the subdir.
19Two constraints make that placement mandatory:
21- `addpath(<literal>)` must be a **leading** statement in the driver, before any
22 other non-comment statement (numbl's static path resolution requires it; the
23 runtime/interpreter path is fine with it too). It also cannot live inside a
24 function file — only the driver. So `hitandrun_sampler.m` can't add the path
25 itself; run `hitandrun_demo.m`, not the sampler directly.
26- Plain subdirectories are otherwise invisible to function resolution — only
27 `addpath`'d dirs (plus root, `+pkg`, `@Class`, `private/`) are searched.
29This works the same in the browser deploy (the worker runs the interpreter,
30which honors the runtime `addpath`).
32## Data flow
34**MATLAB → figure:** set `uihtml(..., 'Data', struct)` or call
35`sendEventToHTMLSource(src, 'eventName', data)`
37**Figure → MATLAB:** call `sendToMATLAB('eventName', value)` (see `bridge.ts`);
38receive via `HTMLEventReceivedFcn`
40## The demo, built in stages (all done)
421. **(done)** Generate a convex region + `N` hit-and-run samples in the script;
43 show region + samples in the figure. The samples are drawn server-side and
44 sent via `Data`.
452. **(done)** Add controls to the figure panel: a **Samples** slider, a
46 **Resample** button, and a **New region** button.
473. **(done)** Wire those controls to the sampler (two-way bridge).
49The figure → script protocol:
51- **Samples** slider (on release) / **Resample**
52 `sendToMATLAB('resample', { n, x, y })`. `x, y` are the *current region's*
53 vertices — the script is **stateless**, so it samples the region it's given
54 and replies with `sendEventToHTMLSource(src, 'samples', { x, y, n })`.
55- **New region**`sendToMATLAB('newRegion', { n })`. The script builds a new
56 region and replies with a full `sendEventToHTMLSource(src, 'data', <payload>)`
57 (same shape as the initial `Data`).
59Ideas for the next iteration: show the chain path / burn-in, animate the walk,
60a "uniform vs. non-uniform target" toggle, or a non-convex region (hit-and-run
61chords become multiple segments).
63## Client-side vs. server-side interactivity
65- **Low-latency / view-only** (e.g. dot size, zoom): update React state only —
66 instant, no MATLAB round-trip.
67- **New samples** (depends on the RNG and the algorithm): `sendToMATLAB`
68 script re-runs → `sendEventToHTMLSource` → React re-renders.
70## Key files
72| File | Purpose |
73|------|---------|
74| `app/src/App.tsx` | Main React component; reads data, hosts the panel |
75| `app/src/render/RegionView.tsx` | 2D canvas renderer (region outline + sample dots) |
76| `app/src/bridge.ts` | `onData` / `onHostEvent` / `sendToMATLAB` helpers (generic; identical across these projects) |
77| `hitandrun_sampler.m` | Opens the figure, sends data, handles `resample`/`newRegion` (figure plumbing: `on_event`, `pack_data`, `pack_samples`) |
78| `helpers/make_region.m` | Random convex region (convex hull of disk points) |
79| `helpers/hit_and_run.m` | The hit-and-run sampler (half-plane chord intersection) |
80| `hitandrun_demo.m` | User-facing driver: `addpath('helpers')` + seed + call the sampler |
82## Local iteration
84Always rebuild the figure app first — both workflows read the prebuilt
85`app/dist/index.html`:
87```
88cd app && npm install && npm run build # produces app/dist/index.html
89cd ..
90```
92`NUMBL` below is a local clone of https://github.com/flatironinstitute/numbl
93(e.g. `~/src/numbl`). Run its CLI with `npx tsx $NUMBL/src/cli.ts …` — no
94global install.
96### A. Quick run via the CLI (fastest inner loop)
98```
99npx tsx $NUMBL/src/cli.ts run hitandrun_demo.m --plot
100```
102`--plot` opens the figure in a browser and keeps the script's session alive so
103figure → script callbacks work (Ctrl+C to stop). Good for iterating on the `.m`
104+ app together.
106### B. Preview the actual GitHub Pages site locally
108This reproduces what the [deploy workflow](.github/workflows/deploy.yml) ships
109(it calls `flatironinstitute/numbl/.github/actions/build-site@main`, which is
110just `cli.ts build-site` after building the site-viewer). The numbl in the
111deployed site runs the `.m` in a **web worker in the browser**, and it keeps a
112live uihtml session there — so figure → script callbacks (`resample`) round-trip
113in the deployed site exactly like in the CLI `--plot` path. (That two-way bridge
114is why the workflow builds numbl from `main` rather than the npm release.)
116```
117# one-time, in the numbl clone: build the browser site-viewer
118( cd $NUMBL && npm ci && npm run build:site-viewer )
120# from this project: bundle project + viewer into _site/
121npx tsx $NUMBL/src/cli.ts build-site . --out _site --base /
123# serve it (localhost is a secure context, so coi-serviceworker.js can set the
124# COOP/COEP headers numbl's WASM needs)
125( cd _site && python3 -m http.server 8080 )
126# → open http://localhost:8080/
127```
129Notes:
130- `--base /` is for serving at localhost root. GitHub Pages serves this project
131 at `/<repo>/`, so the workflow auto-detects `--base /hitandrun-interactive/`.
132 Content is identical; only asset paths differ.
133- `_site/` and `dist/` are git-ignored (see `.gitignore`).
134- The real target is GitHub Pages, where the same single-file app runs against
135 numbl compiled in the browser.
moveopenescclose