Skip to content

Validation

What is checked, against what, and where.

Claim Check Where
RNG and geometry unchanged, bit for bit golden vectors frozen from the original JS prototype (Node 24); native and WASM must match ctest golden_vectors
Math functions equal V8's sampled arguments vs Math.* (100 per function) ctest golden_vectors
Determinism under any query history, tiling, threads world_checks (query order, cache size, 8 threads = 1 thread) ctest world_checks
Microtubule paths every point inside the cell, outside the nucleus, under the cytoplasm surface; z follows the local ceiling (middle third of it populated); few near-vertical steps; few turns tighter than the minimum radius; three scenarios ctest world_checks.microtubules
Dye statistics lattice angles and stagger, ring at 12.5 nm, tip at 24.5 nm, linker range, exponential ON/OFF means, geometric blink count, log-normal brightness world_checks KineticsStats
Persistent sites constant rate over 0-100 s and 10000 s, ON mean, window slicing world_checks
Splat and FFT placement against verbatim copies of the previous implementation; parallel = serial ctest sr_render
Widefield engine job format through a CPU reference host; GPU vs CPU (<= 3e-4 rms from fp16 spectra) ctest widefield, tests/web/wf_gpu_check.mjs, wf_gpu_d3d11
Brightfield engine weak phase grating (thin and 8 slices) vs first-order theory (~1e-5), empty field = 1, energy, serial = parallel; core optical volume: tiling, threads, nucleus volume = ellipsoids ctest brightfield, world_checks, tests/web/bf_split_check.mjs
C++ chirp-Z PSF (ZernikePsf.cpp) vs webSMLM's JS / the Java class 0 / ~1e-12 relative L2 ctest zernike_psf, tools/psf_parity_check/
Chirp-Z PSF vs webSMLM's own chirp-Z n <= 6 Zernikes, double-helix mask, depth shift: 0.0000% relative L2 tools/psf_parity_check/
Chirp-Z vs the old direct quadrature 0.22-0.29% relative L2 history in docs/dev/
PSF and noise models vs SMLM Challenge methodology [sage2019] research comparison; the Challenge ground truth is a measured PSF table, so it gives no Zernike targets docs/dev/vectorial-psf-step4-smlm-challenge-comparison.md
Adapter output unchanged by refactors pixel hashes of fixed configurations tools/adapter_pixel_hash.py

Known deviations

  • Blink PSFs are cut (since 2026-10-07): at the default Renderer.Quality (Realistic) a blink's splat leaves out every camera pixel that would get less than 3e-6 of its photons (Fast: 1e-5; Exhaustive: none), without renormalizing. A movie summed over many frames lacks that far halo; compare with webSMLM, or study the PSF's wings, at Exhaustive. Optics, the halo cut.

  • The cytoplasm mesh uses std::pow, which matches JS only on the libm Node was built with (differences below 1e-6 µm elsewhere).

  • Brightfield: only cytoplasm, nucleus and microtubules make contrast (no nucleoli, vesicles, lipid droplets...: not simulated yet, kept out on purpose); scalar forward multislice, monochromatic, flat Koehler field; CellField only.
  • Widefield: the Gaussian PSF (psf-model=0, not the default) ignores defocus; CellField only.
  • Drift: the z drift of widefield and brightfield frames is interpolated between foci 10 nm apart; the background map does not move with the sample.
  • Not yet verified by eye in every Micro-Manager configuration (headless pymmcore tests cover every property and the render path).