# EEG dementia demo: how it is built

This folder is the live demo embedded on `/projects/eeg-dementia/`. It is static: `index.html`
and `app.js` draw SVG charts over `data.json`, which is exported from the committed results of
[happyc0der/eeg-dementia-graph-transformer](https://github.com/happyc0der/eeg-dementia-graph-transformer)
at commit **`4e0d1506155e5ceb3643750b5ea4e70408e02093`** (2026-09-27, "Credits: list only the
original team").

Nothing is trained, fitted or run in the browser. The only computation on the page is the
evaluation step: argmax of each subject's saved out-of-fold probabilities, the confusion matrix,
per-class recall and balanced accuracy. The page shows the repository's own value next to each
recomputed one.

## Files

| File | What it is |
|---|---|
| `index.html` | Layout, styles, the static text and the team credit line (verbatim from `content/projects/eeg-dementia.md`). Uses `../_shared/demo.css`. |
| `app.js` | The four views: the 2025 training-log replay, the per-subject probability triangle with confusion matrix, the forest plot of all 32 models, and the permutation nulls. Vanilla JS, no libraries. |
| `data.json` | Generated by `build/export_data.py`. Do not edit by hand. About 505 KB (about 220 KB gzipped). |
| `build/export_data.py` | The exporter. Python 3 standard library only. |

No network requests other than these same-origin files. No CDN, fonts, tracking or secrets.

## Regenerate `data.json`

From the portfolio repository root:

```bash
git clone https://github.com/happyc0der/eeg-dementia-graph-transformer.git /tmp/eeg-dementia-src
git -C /tmp/eeg-dementia-src checkout 4e0d1506155e5ceb3643750b5ea4e70408e02093
cd public/demos/eeg-dementia/build
python3 -I export_data.py \
  --repo /tmp/eeg-dementia-src \
  --content ../../../../content/projects/eeg-dementia.md \
  --html ../index.html \
  --out ../data.json
```

Tested with Python 3.14.7. The output is deterministic: rerunning it on the same commit gives a
byte-identical `data.json` (sha1 `c25f031cfae3de251419e3d9682251f2cd588b3a`).

The script reads, all relative to the source repository:

- `results/cv3/<model>/` (21 phase-1 models) and `results/phase2/cv3/<model>/` (11 phase-2 models):
  `predictions_subject.csv` (88 subjects x 10 repeats, probabilities with five decimals),
  `metrics_subject_per_repeat.csv` and `summary.json`
- `results/tables/cv3.csv` and `results/phase2/tables/cv3.csv` (cross-check of the rounded table values)
- `results/phase2/tables/paired_cv3.json` (paired bootstrap against the soft vote)
- `results/permutation/spectral_lr.json`, `results/permutation/rbp_lr.json`,
  `results/phase2/permutation/cbramod_lr.json`
- `legacy/results/spatial_spectral_dim128_20250405/training_log.txt` (the 2025 team run) and
  `.../reeval_matched_features/test_cross_results.txt` (that checkpoint on the 18 held-out subjects)

Before writing anything it checks, and stops with an assertion error otherwise, that:

- recomputing balanced accuracy from the saved probabilities, the way `app.js` does it (numpy
  argmax: first maximum wins), gives every value in each model's `metrics_subject_per_repeat.csv`
  (to the file's five decimals), the mean in `summary.json` (to 1e-9) and the summed confusion
  matrix in `summary.json` exactly, for all 32 models;
- all models share the same labels and the same outer folds;
- every epoch line of the training log is parsed, with no gaps;
- every permutation null lies below its observed value, as the README states;
- `index.html` contains the `credit:` line of `content/projects/eeg-dementia.md` verbatim.

Probabilities are stored as integers (value x 100000), which is exact for the five-decimal CSVs,
so the browser recomputes from the same numbers the check used.

## Team credit

The Spring 2025 project was a four-person NYU course project; the graph transformer and its
training code are mostly Subhrajit Dey's. The demo's first view replays that team model's own
training log and says so under the chart. Everything else on the page comes from the 2026
re-evaluation. The footer carries the content file's credit line word for word, and the export
fails if it drifts.

## Colours

AD `#d55181`, CN `#9085e9`, FTD `#c98500`, each with its own marker shape (circle, square,
triangle). The three were checked as a set (all pairs, protanopia and deuteranopia, against the
`#14121c` surface) with the dataviz palette validator; every check passes.

## Test it locally

```bash
python3 -m http.server 8000 --directory public
# http://localhost:8000/demos/eeg-dementia/
# http://localhost:8000/demos/_shared/frame-test.html?demo=eeg-dementia&h=840
```

At 1400 px wide, every view fits the 840 px frame without scrolling inside it. Narrower frames
scroll inside the demo. Under `prefers-reduced-motion: reduce` the replay button is hidden and
the charts are drawn in their final state. Nothing moves until the visitor presses Replay.

## Licence

The source repository is public domain (The Unlicense). The EEG data (OpenNeuro ds004504, CC0)
are not included here, only per-subject model outputs and summary metrics from the repository.
