Optimization#
Spectrally tunable lighting is naturally an optimization problem. A source has multiple emitters, each emitter has a measured spectral distribution, and a target defines what the mixed spectrum should become.
At a high level:
- Read emitter spectra into a matrix.
- Choose one weight per emitter.
- Mix the spectra with matrix multiplication.
- Compare the mixed spectrum to a target.
- Update weights with an optimizer.
- Apply the final weights with manual mode.
Rust-first workflow#
Use the CLI to capture reproducible emitter data:
enody download-spectral-data -o spectral-data.json
Then build and test the optimizer against that file in Rust. Once the optimizer returns one relative flux value per emitter, apply those weights with the Rust SDK:
use enody::message::{Configuration, Flux};
for (emitter, value) in source.emitters().await?.iter().zip(weights) {
emitter.set_flux(Flux::Relative(value)).await?;
}
fixture
.display(Configuration::Manual, Flux::Relative(1.0))
.await?;
This keeps the hardware-control path in the Rust SDK while allowing optimizer experiments to run offline against captured spectral data.
Python helper bindings#
The Python bindings include tinygrad-based response and color helpers:
| Function | Input shape |
|---|---|
melanopic_response(t) |
(n, 401) |
rhodopic_response(t) |
(n, 401) |
s_cone_response(t) |
(n, 401) |
m_cone_response(t) |
(n, 401) |
l_cone_response(t) |
(n, 401) |
cie_x_response(t) |
(n, 401) |
cie_y_response(t) |
(n, 401) |
cie_z_response(t) |
(n, 401) |
cie_1931_chromaticity(t) |
(n, 401) |
ssi(test, reference) |
(n, 301) |
JavaScript helpers#
The JavaScript SDK includes typed-array response and optimizer helpers:
| Function / type | Input shape |
|---|---|
melanopicResponse(distributions) |
401 or (n, 401) |
rhodopicResponse(distributions) |
401 or (n, 401) |
sConeResponse(distributions) |
401 or (n, 401) |
mConeResponse(distributions) |
401 or (n, 401) |
lConeResponse(distributions) |
401 or (n, 401) |
cie1931Chromaticity(distributions) |
401 or (n, 401) |
computeSSI(test301, reference301) |
301 |
SpectralOptimizer |
SPD matrix as numEmitters * 401 |