|
| 1 | +# JAXTPC Documentation & Notebooks Plan |
| 2 | + |
| 3 | +Roadmap for turning JAXTPC into a documented, usable library for four audiences: |
| 4 | +external/new users, internal production users, ML/reco researchers, and |
| 5 | +extenders/developers. This is a planning artifact — check items off as built. |
| 6 | + |
| 7 | +Status legend: `[ ]` todo · `[~]` partial/exists-needs-work · `[x]` done |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +## 1. Goals |
| 12 | + |
| 13 | +- A new user can **install, run a simulation, and understand the output** in minutes. |
| 14 | +- The project's **non-obvious conventions** (units, coordinate frame, capacity |
| 15 | + sizing, the two execution paths) are written down where users will find them — |
| 16 | + not buried in `CLAUDE.md` (which ships to no one) or in tribal memory. |
| 17 | +- Production, differentiable/ML, and extension workflows each have a clear path. |
| 18 | +- Docs stay honest: API reference is generated from docstrings; notebooks are |
| 19 | + executed in CI; the existing nbstripout filter keeps notebook diffs clean. |
| 20 | + |
| 21 | +## 2. Audiences and what each needs |
| 22 | + |
| 23 | +| Audience | Primary needs | Entry points | |
| 24 | +|---|---|---| |
| 25 | +| **External / new users** | install, runnable quickstart, physics concepts, citation | Quickstart, NB 00–04, Concepts | |
| 26 | +| **Internal production users** | batch pipeline, HDF5 schemas, profiler/capacity sizing, slurm, dataset specifics | Production docs, NB 07 | |
| 27 | +| **ML / reco researchers** | differentiable path, gradients, truth correspondence, losses, point clouds | Differentiable docs, NB 06, 08 | |
| 28 | +| **Extenders / devs** | config schema, adding detectors, frame/uniformity invariants, tests & CI | Config reference, Contributing, NB 01/09 | |
| 29 | + |
| 30 | +## 3. Tooling decision |
| 31 | + |
| 32 | +- **Site generator:** `mkdocs` + `mkdocs-material` (low-effort, standard for |
| 33 | + scientific Python; search, nav, dark mode out of the box). |
| 34 | +- **API reference:** `mkdocstrings[python]` — auto-generated from the (now |
| 35 | + corrected) numpy-style docstrings in `tools/`. No hand-maintained API pages. |
| 36 | +- **Notebook embedding:** `mkdocs-jupyter` renders the `examples/*.ipynb` as doc |
| 37 | + pages directly, so tutorials live in one place and are runnable. |
| 38 | +- **Hosting:** GitHub Pages via a `docs` CI job (`mkdocs gh-deploy` or an Actions |
| 39 | + workflow). Add a `docs` extra in `pyproject` for the doc dependencies. |
| 40 | +- **Honesty checks (CI):** execute notebooks (`jupyter nbconvert --execute`) on a |
| 41 | + small/synthetic path so stale APIs fail loudly; optional link-check. |
| 42 | + |
| 43 | +## 4. Prerequisite: packaging (makes "install" real) |
| 44 | + |
| 45 | +"For people to use" requires a real install story. Today everything is |
| 46 | +`import tools` from the repo root (generic top-level names `tools`/`config`/ |
| 47 | +`scripts` will collide on install). This is the foundation the install/quickstart |
| 48 | +pages rest on. |
| 49 | + |
| 50 | +- `[ ]` **`pyproject.toml`** — PEP 621 metadata: name `jaxtpc`, version (sync to |
| 51 | + the existing `0.9.0` tag + a `__version__`), `requires-python>=3.10`, |
| 52 | + dependencies from `requirements.txt` (jax bounded `>=0.4,<0.7`, numpy, scipy, |
| 53 | + matplotlib, h5py, hdf5plugin, pyyaml, pillow), optional extras: `dev` |
| 54 | + (pytest, nbstripout), `docs` (mkdocs-material, mkdocstrings, mkdocs-jupyter), |
| 55 | + `gpu` (jax[cuda12]). |
| 56 | +- `[ ]` **Package layout** — move the importable code under a single namespace |
| 57 | + (`src/jaxtpc/{tools,production,profiler,viewer}`) and rewrite imports |
| 58 | + (`tools.` → `jaxtpc.tools.`). Breaking; do as one focused PR. *Decision needed:* |
| 59 | + do this now vs ship as a repo-root project first. (See the production-readiness |
| 60 | + assessment for detail.) |
| 61 | +- `[ ]` **`console_scripts`** — `jaxtpc-batch`, `jaxtpc-setup-production`, |
| 62 | + `jaxtpc-viewer`, `jaxtpc-export-gif`, `jaxtpc-make-labl`. |
| 63 | +- `[ ]` **`LICENSE`**, `[ ]` **`CITATION.cff`** (this is a tool that will be cited), |
| 64 | + `[ ]` **`CONTRIBUTING.md`**. |
| 65 | +- `[ ]` **Ship package data** — `tools/responses/*.npz`, `tools/data/*.csv`, |
| 66 | + `config/*.yaml`, and the runtime assets currently outside the package |
| 67 | + (`config/noise_spectrum.npz`, `config/pixel_response.npz`, the SCE map) via |
| 68 | + `package-data`/`importlib.resources`. Note: those three assets are loaded today |
| 69 | + via `tools/../config` and will break on install unless relocated/declared. |
| 70 | + |
| 71 | +## 5. The "must-capture" tribal knowledge (dedicated treatment) |
| 72 | + |
| 73 | +These are the things that bite people and currently live only in `CLAUDE.md` or |
| 74 | +nowhere. Each gets a focused doc page **and** a notebook section. |
| 75 | + |
| 76 | +1. **Units convention** — wire hits in **ENC** (electrons), pixel hits in **ADC**; |
| 77 | + `inter_thresh` / `threshold_adc` / `corr_threshold` mean different things per |
| 78 | + readout. The single biggest footgun. (Source: `CLAUDE.md` units table.) |
| 79 | +2. **Local coordinate frame** — deposits are transformed to volume-local/centered |
| 80 | + coords (`y_local = y_global - y_center`; `x_local` anode-referenced via |
| 81 | + `drift_direction`). All per-volume geometry reduces to one local frame so the |
| 82 | + JIT body uses fixed constants. The recently-fixed pixel-origin bug lived |
| 83 | + exactly here — document the invariant (and the geometry-uniformity assumption |
| 84 | + across volumes). |
| 85 | +3. **Capacity sizing** — `total_pad`, `maxg`/`maxg_medium`, `max_keys`, |
| 86 | + `response_chunk`/`hits_chunk`, `max_buckets`, analytic box dims: what each |
| 87 | + bounds, how the profiler sizes them, and overflow behavior (hard crash vs |
| 88 | + logged-and-reprocess). (Source: `profiler/README.md`.) |
| 89 | +4. **Two execution paths** — `process_event` (production, batched, JIT) vs |
| 90 | + `forward`/`forward_segments` (differentiable, remat); when to use which. |
| 91 | +5. **Output schema** — the sensor / step / hits (+ separate labl) HDF5 files, |
| 92 | + their delta/CSR encodings, codecs, and 1-based group ids. |
| 93 | + |
| 94 | +## 6. Documentation site map (`docs/`) |
| 95 | + |
| 96 | +Each page notes: **[audience]** · content · *source material to migrate*. |
| 97 | + |
| 98 | +``` |
| 99 | +docs/ |
| 100 | + index.md [all] what/why, capabilities, the two paths, links |
| 101 | + install.md [all] pip install, GPU JAX, verify; *needs pyproject* |
| 102 | + quickstart.md [external] 30-line runnable example -> NB 00 |
| 103 | +
|
| 104 | + concepts/ |
| 105 | + architecture.md [dev] DetectorSimulator, factory/closure pattern, scan/vmap over volumes *from CLAUDE.md* |
| 106 | + coordinates.md [dev] local frame, centering, anode refs, uniformity invariant |
| 107 | + config-vs-params.md [all] SimConfig (static) vs SimParams (dynamic), recompilation |
| 108 | + paths.md [all] production vs differentiable |
| 109 | +
|
| 110 | + physics/ |
| 111 | + overview.md [physics] the full response chain, one diagram |
| 112 | + recombination.md [physics] modified-box / EMB / passthrough; Q & L; angular dep |
| 113 | + drift-diffusion.md [physics] drift, lifetime attenuation, DCT/spatial-conv diffusion kernels |
| 114 | + response-kernels.md [physics] DKernel table, s-level interpolation, wire vs pixel kernels |
| 115 | + electronics-noise.md [physics] RC*RC shaping, intrinsic + coherent noise, digitization |
| 116 | + sce.md [physics] space charge: maps, time-primary corrections, displacement |
| 117 | + units.md [all] **ENC vs ADC** convention + threshold-units table *from CLAUDE.md* |
| 118 | +
|
| 119 | + detector/ |
| 120 | + config-schema.md [dev] full YAML reference (volumes, geometry, planes/pixel, simulation, readout, electric_field) |
| 121 | + presets.md [all] SBND, MicroBooNE, ICARUS, DUNE FD1, ND-LAr, cubic wire/pixel |
| 122 | + wire-vs-pixel.md [all] readout types, when each, output differences |
| 123 | +
|
| 124 | + production/ |
| 125 | + batch.md [internal] run_batch CLI, threaded save, workers *from production/README.md* |
| 126 | + data-formats.md [internal/ML] sensor/step/hits/labl HDF5 schema, encodings, codecs *from production/README.md* |
| 127 | + profiler.md [internal] capacity sizing, setup_production, overflow/reprocess *from profiler/README.md* |
| 128 | + slurm.md [internal] array drivers, resume, dataset layout *from production/RUN_PRODUCTION.md* |
| 129 | +
|
| 130 | + differentiable/ |
| 131 | + overview.md [ML] forward / forward_segments, remat, what's differentiable |
| 132 | + losses.md [ML] multi-scale spectral MSE, point-cloud / OT losses |
| 133 | + optimization.md [ML] gradient examples, particle_generator, a fit demo -> NB 08 |
| 134 | +
|
| 135 | + truth/ |
| 136 | + track-hits.md [ML/internal] group->track correspondence, qs_fractions, labeling |
| 137 | +
|
| 138 | + viz/ |
| 139 | + plotting.md [all] visualization + pixel_visualization helpers |
| 140 | + viewer.md [all] interactive 3D/2D viewer + GIF export *from viewer/README.md* |
| 141 | +
|
| 142 | + reference/ |
| 143 | + api/ [dev] auto-generated (mkdocstrings) per module |
| 144 | + glossary.md [all] terms + gotchas (units, overflow, frames) |
| 145 | + faq.md [all] common errors and fixes |
| 146 | + citation.md [external] how to cite |
| 147 | +
|
| 148 | + contributing/ |
| 149 | + development.md [dev] env, tests (`pytest -m "not slow"`), CI gates *from tests/TESTS.md* |
| 150 | + invariants.md [dev] frame & geometry-uniformity invariants, adding-a-detector checklist |
| 151 | +``` |
| 152 | + |
| 153 | +Most pages are **migration + correction** of existing `README`/`CLAUDE.md` |
| 154 | +content, not greenfield writing. After migration, `CLAUDE.md` shrinks to |
| 155 | +AI-assistant guidance + pointers into `docs/`. |
| 156 | + |
| 157 | +## 7. Notebook series (`examples/`) |
| 158 | + |
| 159 | +Numbered, progressive. Each: **[audience]** · content · status. |
| 160 | + |
| 161 | +| # | Notebook | Audience | Content | Status | |
| 162 | +|---|---|---|---|---| |
| 163 | +| 00 | `00_quickstart.ipynb` | external | install check → synthetic event → wire sim → 4 plots, minimal | `[ ]` new (extract from `run_simulation`) | |
| 164 | +| 01 | `01_detector_config.ipynb` | all/dev | YAML anatomy, multi-volume, visualize geometry, wire vs pixel | `[ ]` new | |
| 165 | +| 02 | `02_physics_walkthrough.ipynb` | physics | one event, a plot at each pipeline stage (Q/L→drift→diffusion→kernel→electronics→noise→ADC) | `[ ]` new | |
| 166 | +| 03 | `03_wire_vs_pixel_units.ipynb` | all | side-by-side; ENC vs ADC made concrete; thresholds | `[ ]` new | |
| 167 | +| 04 | `04_recombination_models.ipynb` | physics | modified-box vs EMB vs passthrough; angular dependence | `[ ]` new | |
| 168 | +| 05 | `05_space_charge.ipynb` | physics | generate/load SCE maps, apply, visualize distortion | `[ ]` new | |
| 169 | +| 06 | `06_truth_and_track_hits.ipynb` | ML/internal | group→track correspondence; per-particle labels | `[ ]` new | |
| 170 | +| 07 | `07_production_pipeline.ipynb` | internal | run_batch, the 3 HDF5 files, profiler sizing, load output | `[~]` fold in `production/view_production.ipynb` | |
| 171 | +| 08 | `08_differentiable.ipynb` | ML | forward_segments, gradients wrt velocity/lifetime, gradient-descent fit demo | `[ ]` new | |
| 172 | +| 09 | `09_custom_detector.ipynb` | dev | build a new geometry end-to-end | `[ ]` new | |
| 173 | +| A1 | `response_kernels.ipynb` | physics/dev | kernel + diffusion visualization (appendix) | `[~]` existing `tools/responses/response_visualization.ipynb` | |
| 174 | + |
| 175 | +Existing `run_simulation.ipynb` / `run_pixel_simulation.ipynb` become the basis |
| 176 | +for 00/02/03 (they already run self-contained on a synthetic event). Keep all |
| 177 | +notebooks runnable with **no external data** (synthetic-event helper) so they |
| 178 | +work in CI and for external users; show the `load_event(...)` swap for real data. |
| 179 | + |
| 180 | +## 8. Content migration map (existing → destination) |
| 181 | + |
| 182 | +| Existing | Destination | |
| 183 | +|---|---| |
| 184 | +| `README.md` | trimmed landing page + `docs/index.md`, `install.md`, `quickstart.md` | |
| 185 | +| `CLAUDE.md` (architecture, units, data types, pipeline) | `docs/concepts/*`, `docs/physics/*`, `docs/detector/config-schema.md`; CLAUDE.md → assistant-only + links | |
| 186 | +| `production/README.md` | `docs/production/batch.md`, `data-formats.md` | |
| 187 | +| `production/RUN_PRODUCTION.md` | `docs/production/slurm.md` (fix stale config filenames) | |
| 188 | +| `profiler/README.md` | `docs/production/profiler.md` | |
| 189 | +| `viewer/README.md` | `docs/viz/viewer.md` | |
| 190 | +| `tests/TESTS.md` | `docs/contributing/development.md` | |
| 191 | +| 4 working notebooks | `examples/` (renumbered) | |
| 192 | + |
| 193 | +## 9. Phased execution plan |
| 194 | + |
| 195 | +**Phase 0 — foundation (unblocks "install + run")** |
| 196 | +- `[ ]` `pyproject.toml`, `LICENSE`, `CITATION.cff` |
| 197 | +- `[ ]` decide packaging layout (src/jaxtpc namespace vs repo-root) |
| 198 | +- `[ ]` relocate/declare the 3 out-of-package runtime assets |
| 199 | + |
| 200 | +**Phase 1 — front door (external users)** |
| 201 | +- `[ ]` mkdocs skeleton + CI deploy + API auto-gen |
| 202 | +- `[ ]` `index`, `install`, `quickstart`; NB 00 |
| 203 | +- `[ ]` `physics/units.md` + `concepts/coordinates.md` (the top footguns) |
| 204 | + |
| 205 | +**Phase 2 — physics & tutorials** |
| 206 | +- `[ ]` NB 01–04; physics pages; detector config schema |
| 207 | + |
| 208 | +**Phase 3 — production (internal)** |
| 209 | +- `[ ]` production pages (migrate + fix stale names); NB 07 |
| 210 | + |
| 211 | +**Phase 4 — differentiable/ML** |
| 212 | +- `[ ]` differentiable pages; losses/pointcloud; NB 06, 08 |
| 213 | + |
| 214 | +**Phase 5 — extension & polish** |
| 215 | +- `[ ]` NB 09; contributing/invariants; glossary/FAQ; SCE page + NB 05 |
| 216 | + |
| 217 | +## 10. Keeping docs honest (maintenance) |
| 218 | + |
| 219 | +- API reference is generated from docstrings — fix docstrings, not duplicate prose. |
| 220 | +- Notebooks executed in CI (synthetic-event path) so a stale API fails the build. |
| 221 | +- `nbstripout` filter + `notebook-output-check` CI keep notebook diffs clean. |
| 222 | +- A short "docs touched?" reminder when public APIs change (PR checklist in |
| 223 | + `contributing/`). |
| 224 | +- Single source of truth for the units table and capacity glossary — link to it, |
| 225 | + don't restate. |
| 226 | + |
| 227 | +--- |
| 228 | + |
| 229 | +### Open decisions (need a call before/within Phase 0–1) |
| 230 | +1. **Packaging namespace** — adopt `src/jaxtpc/` now (breaking, clean) or ship |
| 231 | + repo-root and defer? Affects every import and the install page. |
| 232 | +2. **Docs hosting** — public GitHub Pages (external audience) vs internal only. |
| 233 | +3. **Notebook execution in CI** — full synthetic run (slower, catches more) vs |
| 234 | + import/collect-only (fast). |
0 commit comments