The scene definition and power normalization are in
../primitive-emitter-studies/README.md.
The estimator's multi-source measure is in
../custom-combinations/README.md.
This directory retains the experiment runner and analysis. Runs use their own runtime directory and never overwrite the user's working application settings. The runner copies the current Release binary into that directory and records its SHA-256 beside every film. A changed binary or configuration refuses stale resume.
python docs/emitter-study/run_study.py C:/path/to/run pilot
python docs/emitter-study/run_study.py C:/path/to/run bench --passes 1024 --seeds 6
python docs/emitter-study/run_study.py C:/path/to/run composite --passes 1024 --seeds 6
python docs/emitter-study/run_study.py C:/path/to/run beauty --passes 4096 --width 640 --height 400
python docs/emitter-study/analyze_study.py C:/path/to/run C:/path/to/analysis --min-seeds 6
python docs/emitter-study/analyze_study.py --self-test
The benchmark's film dimensions default to 160×100. The runner deterministically
shuffles the order of methods and seed-key runs. The native measurement encloses
the primary CPU renderPass, with eight passes omitted from timing as warmup.
It does not include application startup, UI, display or film dumping. The film
still contains every pass: estimated rendering time is total passes multiplied
by measured post-warmup milliseconds per pass, not just the shorter timed span.
These configurations isolate direct medium scattering: minimum bounce 0,
maximum bounce 1, no surface composition or correlated pool, and camera-far
capping disabled. They measure the declared primitive-layer target, not a full
surface-plus-multiple-scattering render. Exact per-run settings remain beside
each film and in the generated protocol. An optional machine.json in the run
root is copied into that protocol; it records the actual CPU experiment host
separately from the OpenGL display renderer.
What the analysis measures
For each condition, let mu_m be method m's mean image over K seed-key runs.
Let mu_pool be the equal-weight mean of all required methods' mu_m, and define
the shared denominator D = sum_pixel,RGB mu_pool^2. For each method:
V = sum_pixel,RGB sample_variance(seed films, ddof=1) / D
per-pass proxy = N * V
variance-cost proxy = N * V * median(native milliseconds per pass)
Here the seed films are N-pass running means. Lower variance-cost proxy means less observed seed dispersion for the measured cost. It is not a ground-truth MSE and is not proof of lower bias, finite variance or asymptotic convergence. The pooled denominator is itself estimated and is shared within each condition; it is not a reference solution. Six repeats remain a small sample for methods with rare, very large contributions. No confidence intervals or universal winner are inferred. Timing min/max columns are observed run spread only.
The mean luminance, seed standard deviation/range and ratio to pooled mean are separate energy-consistency diagnostics. Agreement among methods cannot exclude a shared error. Broad spatially dark regions are retained: there is no method-dependent brightness threshold, image mask, exposure or clipping in the numerical calculation.
Each pass draws one record per active member; a record may yield paired roots. One six-member pass therefore differs from one UV-only pass. The cost proxy accounts for measured pass cost rather than treating these as equal-work samples.
Reference scope
The analysis does not use strategy 2 as ground truth. Its existing direct continuation-to-emitter term has an angular-profile limitation, so agreement in an all-diffuse scene does not establish a reference for the laser/cone room. Separate native conformance tests must state their path class, visibility rules, camera geometry and emitter weighting. A correct multi-source density ledger and an image's finite-sample dispersion answer different questions.
Retained outputs
summary.csv/summary.json: per-method variance, timing, mean-energy and provenance statistics.raw-timings.csv: every completed run's actual timing, dimensions, passes, seed key and binary/config/film hashes. Launch seconds are diagnostic only.protocol.json: exact common conditions, formulas, seed keys, source hashes, incompleteness checks and display transforms.factorial-*.png/.svg: common-scale heatmaps for per-pass dispersion, native cost and their product. Rows are profiles, columns are source sizes.composite-*.png/.svg: the three complete rooms. Their spatial arrangement, overlapping contributions and source-selection probabilities remain part of the test; only the recentered probes isolate the source properties.- Beauty PNGs preserve each full native frame and use a shared exposure with
1-exp(-exposure*max(linear RGB,0)), then sRGB encoding. There is no crop, denoising, local contrast edit or synthetic image content. Measurements use the unchanged float films, before this display transform.
The analyzer validates the recorded config/film hashes and timing metadata. It requires all eight intended probe methods, or all four composite methods, with matching seed-key sets. Incomplete conditions are listed and omitted from statistics; they are never silently treated as zero-valued results.
The retained 2026-09-13 results include the compact summary CSV and exact protocol, observed findings, executable provenance and the separate high-resolution stress disclosure. Full films and run records remain in the external experiment directory recorded by that protocol.