@photivra/engine 2.18.0 → 2.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +68 -1
- package/CITATION.cff +1 -1
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/dist/capture/focus-control.js +2 -75
- package/dist/capture/focus-control.js.map +1 -1
- package/dist/capture/native-environment-lean.d.ts +1 -0
- package/dist/capture/native-environment-lean.js +1 -1
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-environment-optical-stage.d.ts +1 -0
- package/dist/capture/native-environment-optical-stage.js +2 -5
- package/dist/capture/native-environment-optical-stage.js.map +1 -1
- package/dist/capture/native-environment-raw.js +1 -5
- package/dist/capture/native-environment-raw.js.map +1 -1
- package/dist/capture/release-sequence.js +2 -47
- package/dist/capture/release-sequence.js.map +1 -1
- package/dist/color/white-balance.d.ts +2 -0
- package/dist/color/white-balance.js +3 -56
- package/dist/color/white-balance.js.map +1 -1
- package/dist/composition/image-formation-plan.d.ts +1 -0
- package/dist/composition/image-formation-plan.js +3 -49
- package/dist/composition/image-formation-plan.js.map +1 -1
- package/dist/core/evidence-provenance.js +1 -16
- package/dist/core/evidence-provenance.js.map +1 -1
- package/dist/core/record-validation.d.ts +54 -0
- package/dist/core/record-validation.js +176 -0
- package/dist/core/record-validation.js.map +1 -1
- package/dist/core/scientific-assurance.js +1 -18
- package/dist/core/scientific-assurance.js.map +1 -1
- package/dist/core/shared-helpers.d.ts +33 -0
- package/dist/core/shared-helpers.js +34 -0
- package/dist/core/shared-helpers.js.map +1 -0
- package/dist/core/spectral-composition.js +1 -36
- package/dist/core/spectral-composition.js.map +1 -1
- package/dist/core/spectral.js +1 -19
- package/dist/core/spectral.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/equipment/exposure-capabilities.d.ts +1 -0
- package/dist/equipment/exposure-capabilities.js +2 -36
- package/dist/equipment/exposure-capabilities.js.map +1 -1
- package/dist/equipment/iso-capabilities.js +2 -49
- package/dist/equipment/iso-capabilities.js.map +1 -1
- package/dist/equipment/metering-capabilities.js +1 -26
- package/dist/equipment/metering-capabilities.js.map +1 -1
- package/dist/equipment/release-capabilities.js +1 -53
- package/dist/equipment/release-capabilities.js.map +1 -1
- package/dist/exposure/auto-iso-slowest-shutter.js +1 -7
- package/dist/exposure/auto-iso-slowest-shutter.js.map +1 -1
- package/dist/exposure/exposure-duration-control.js +1 -16
- package/dist/exposure/exposure-duration-control.js.map +1 -1
- package/dist/exposure/exposure-mode-resolver.js +1 -17
- package/dist/exposure/exposure-mode-resolver.js.map +1 -1
- package/dist/exposure/filtered-exposure-time.d.ts +93 -0
- package/dist/exposure/filtered-exposure-time.js +129 -0
- package/dist/exposure/filtered-exposure-time.js.map +1 -0
- package/dist/exposure/flash-ttl.d.ts +1 -0
- package/dist/exposure/flash-ttl.js +1 -1
- package/dist/exposure/flash-ttl.js.map +1 -1
- package/dist/exposure/flash.js +1 -49
- package/dist/exposure/flash.js.map +1 -1
- package/dist/exposure/metering-scene-radiance.js +1 -25
- package/dist/exposure/metering-scene-radiance.js.map +1 -1
- package/dist/exposure/metering-target.js +1 -30
- package/dist/exposure/metering-target.js.map +1 -1
- package/dist/exposure/metering-temporal.js +1 -8
- package/dist/exposure/metering-temporal.js.map +1 -1
- package/dist/exposure/metering.js +1 -72
- package/dist/exposure/metering.js.map +1 -1
- package/dist/exposure/program-line.js +1 -45
- package/dist/exposure/program-line.js.map +1 -1
- package/dist/facade/develop-joined-parts.d.ts +29 -0
- package/dist/facade/develop-joined-parts.js +33 -0
- package/dist/facade/develop-joined-parts.js.map +1 -0
- package/dist/facade/generic-lens-capture.d.ts +4 -2
- package/dist/facade/generic-lens-capture.js +4 -2
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +37 -5
- package/dist/facade/simulate-capture.js +153 -96
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.js +1 -3
- package/dist/gpu/chart-composite-gpu.js.map +1 -1
- package/dist/gpu/chart-radiance-gpu.js +1 -5
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/gpu/display-view-quality-gpu.d.ts +13 -1
- package/dist/gpu/display-view-quality-gpu.js +4 -8
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.js +3 -25
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/gpu/sensor-stage-gpu.js +1 -5
- package/dist/gpu/sensor-stage-gpu.js.map +1 -1
- package/dist/gpu/webgpu-runtime.d.ts +2 -0
- package/dist/gpu/webgpu-runtime.js +3 -0
- package/dist/gpu/webgpu-runtime.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/motion/camera-rotation.js +1 -6
- package/dist/motion/camera-rotation.js.map +1 -1
- package/dist/motion/capture-rotation-inverse-mapping.d.ts +12 -0
- package/dist/motion/capture-rotation-inverse-mapping.js +2 -2
- package/dist/motion/capture-rotation-inverse-mapping.js.map +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.d.ts +1 -0
- package/dist/motion/capture-rotation-temporal-quadrature.js +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.js.map +1 -1
- package/dist/motion/capture-rotation-trajectory.js +2 -17
- package/dist/motion/capture-rotation-trajectory.js.map +1 -1
- package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts +1 -0
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js +3 -14
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js.map +1 -1
- package/dist/motion/extended-object-projection.js +5 -40
- package/dist/motion/extended-object-projection.js.map +1 -1
- package/dist/optics/atmospheric-haze.js +1 -7
- package/dist/optics/atmospheric-haze.js.map +1 -1
- package/dist/optics/brown-conrady-distortion.js +1 -7
- package/dist/optics/brown-conrady-distortion.js.map +1 -1
- package/dist/optics/complex-pupil-psf.d.ts +1 -0
- package/dist/optics/complex-pupil-psf.js +2 -84
- package/dist/optics/complex-pupil-psf.js.map +1 -1
- package/dist/optics/focus-state.js +1 -11
- package/dist/optics/focus-state.js.map +1 -1
- package/dist/optics/front-of-lens-filter.d.ts +5 -0
- package/dist/optics/front-of-lens-filter.js +3 -65
- package/dist/optics/front-of-lens-filter.js.map +1 -1
- package/dist/optics/generic-nd-filter-presets.d.ts +12 -0
- package/dist/optics/generic-nd-filter-presets.js +48 -0
- package/dist/optics/generic-nd-filter-presets.js.map +1 -0
- package/dist/optics/illumination-vignetting.js +1 -6
- package/dist/optics/illumination-vignetting.js.map +1 -1
- package/dist/optics/lens-psf-profile.d.ts +4 -1
- package/dist/optics/lens-psf-profile.js +12 -111
- package/dist/optics/lens-psf-profile.js.map +1 -1
- package/dist/optics/longitudinal-chromatic-aberration.js +1 -7
- package/dist/optics/longitudinal-chromatic-aberration.js.map +1 -1
- package/dist/optics/pupil-vignetting.js +1 -7
- package/dist/optics/pupil-vignetting.js.map +1 -1
- package/dist/optics/radial-distortion.js +1 -6
- package/dist/optics/radial-distortion.js.map +1 -1
- package/dist/optics/scene-to-sensor-irradiance.js +4 -96
- package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
- package/dist/optics/stray-light.d.ts +1 -0
- package/dist/optics/stray-light.js +1 -1
- package/dist/optics/stray-light.js.map +1 -1
- package/dist/optics/zernike-wavefront.js +1 -7
- package/dist/optics/zernike-wavefront.js.map +1 -1
- package/dist/output/capture-geometry.js +1 -8
- package/dist/output/capture-geometry.js.map +1 -1
- package/dist/output/developed-lens-corrections.d.ts +62 -0
- package/dist/output/developed-lens-corrections.js +135 -0
- package/dist/output/developed-lens-corrections.js.map +1 -0
- package/dist/output/generic-lens-corrections.d.ts +2 -6
- package/dist/output/generic-lens-corrections.js +3 -6
- package/dist/output/generic-lens-corrections.js.map +1 -1
- package/dist/output/geometric-transforms.js +1 -4
- package/dist/output/geometric-transforms.js.map +1 -1
- package/dist/output/native-capture-sdr.d.ts +2 -2
- package/dist/output/native-capture-sdr.js +3 -2
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/processing/development-detail.d.ts +29 -0
- package/dist/processing/development-detail.js +128 -107
- package/dist/processing/development-detail.js.map +1 -1
- package/dist/schema/illumination-temporal.js +3 -72
- package/dist/schema/illumination-temporal.js.map +1 -1
- package/dist/schema/illumination.d.ts +1 -0
- package/dist/schema/illumination.js +2 -65
- package/dist/schema/illumination.js.map +1 -1
- package/dist/schema/scene-radiance-temporal.js +2 -14
- package/dist/schema/scene-radiance-temporal.js.map +1 -1
- package/dist/schema/scene-radiance.js +2 -60
- package/dist/schema/scene-radiance.js.map +1 -1
- package/dist/schema/validation.d.ts +2 -0
- package/dist/schema/validation.js +2 -17
- package/dist/schema/validation.js.map +1 -1
- package/dist/sensor/accumulated-charge.js +2 -59
- package/dist/sensor/accumulated-charge.js.map +1 -1
- package/dist/sensor/architecture.js +1 -16
- package/dist/sensor/architecture.js.map +1 -1
- package/dist/sensor/camera-saturation-capacity.d.ts +1 -0
- package/dist/sensor/camera-saturation-capacity.js +3 -55
- package/dist/sensor/camera-saturation-capacity.js.map +1 -1
- package/dist/sensor/capture-color-sampling-binding.js +1 -26
- package/dist/sensor/capture-color-sampling-binding.js.map +1 -1
- package/dist/sensor/capture-mode-timing.js +1 -39
- package/dist/sensor/capture-mode-timing.js.map +1 -1
- package/dist/sensor/capture-mode.js +1 -23
- package/dist/sensor/capture-mode.js.map +1 -1
- package/dist/sensor/color-sampling.js +1 -26
- package/dist/sensor/color-sampling.js.map +1 -1
- package/dist/sensor/constant-rate-temporal-integration.js +2 -46
- package/dist/sensor/constant-rate-temporal-integration.js.map +1 -1
- package/dist/sensor/dark-current.js +2 -45
- package/dist/sensor/dark-current.js.map +1 -1
- package/dist/sensor/eqe-electron-rate.js +2 -35
- package/dist/sensor/eqe-electron-rate.js.map +1 -1
- package/dist/sensor/exposure-window.d.ts +5 -0
- package/dist/sensor/exposure-window.js +7 -22
- package/dist/sensor/exposure-window.js.map +1 -1
- package/dist/sensor/iso-gain.js +1 -7
- package/dist/sensor/iso-gain.js.map +1 -1
- package/dist/sensor/iso-signal-chain.js +1 -43
- package/dist/sensor/iso-signal-chain.js.map +1 -1
- package/dist/sensor/optical-stack.js +1 -25
- package/dist/sensor/optical-stack.js.map +1 -1
- package/dist/sensor/photon-energy.js +1 -26
- package/dist/sensor/photon-energy.js.map +1 -1
- package/dist/sensor/physical-charge-capacity.js +3 -77
- package/dist/sensor/physical-charge-capacity.js.map +1 -1
- package/dist/sensor/radiometry-readiness.js +2 -23
- package/dist/sensor/radiometry-readiness.js.map +1 -1
- package/dist/sensor/raw-readout.d.ts +3 -0
- package/dist/sensor/raw-readout.js +4 -66
- package/dist/sensor/raw-readout.js.map +1 -1
- package/dist/sensor/raw-reconstruction.js +2 -64
- package/dist/sensor/raw-reconstruction.js.map +1 -1
- package/dist/sensor/readout-exposure-linkage.js +1 -9
- package/dist/sensor/readout-exposure-linkage.js.map +1 -1
- package/dist/sensor/readout-timing.js +3 -57
- package/dist/sensor/readout-timing.js.map +1 -1
- package/dist/sensor/response-application-compatibility.d.ts +2 -0
- package/dist/sensor/response-application-compatibility.js +3 -29
- package/dist/sensor/response-application-compatibility.js.map +1 -1
- package/dist/sensor/response-operating-range.d.ts +1 -0
- package/dist/sensor/response-operating-range.js +3 -79
- package/dist/sensor/response-operating-range.js.map +1 -1
- package/dist/sensor/responsivity-photocurrent.js +4 -108
- package/dist/sensor/responsivity-photocurrent.js.map +1 -1
- package/dist/sensor/sampling-aperture.js +1 -25
- package/dist/sensor/sampling-aperture.js.map +1 -1
- package/dist/sensor/spatial-sample-reduction.js +2 -19
- package/dist/sensor/spatial-sample-reduction.js.map +1 -1
- package/dist/sensor/spatial-sampling-quadrature.js +1 -3
- package/dist/sensor/spatial-sampling-quadrature.js.map +1 -1
- package/dist/sensor/spatio-spectral-reduction.js +1 -18
- package/dist/sensor/spatio-spectral-reduction.js.map +1 -1
- package/dist/sensor/spectral-coverage.d.ts +10 -1
- package/dist/sensor/spectral-coverage.js +1 -1
- package/dist/sensor/spectral-coverage.js.map +1 -1
- package/dist/sensor/spectral-quadrature.js +2 -35
- package/dist/sensor/spectral-quadrature.js.map +1 -1
- package/dist/sensor/spectral-response.js +1 -47
- package/dist/sensor/spectral-response.js.map +1 -1
- package/dist/stabilization/camera-shake.js +1 -6
- package/dist/stabilization/camera-shake.js.map +1 -1
- package/dist/stabilization/system.js +2 -80
- package/dist/stabilization/system.js.map +1 -1
- package/docs/AGENT_GUIDE.md +1 -0
- package/docs/API_REFERENCE.md +41 -2
- package/docs/QUICK_START.md +90 -8
- package/docs/USAGE.md +47 -2
- package/docs/api/core-version.md +1 -1
- package/docs/api/exports.json +53 -3
- package/docs/api/exposure-filtered-exposure-time.md +105 -0
- package/docs/api/facade-develop-joined-parts.md +32 -0
- package/docs/api/facade-simulate-capture.md +36 -5
- package/docs/api/optics-generic-nd-filter-presets.md +34 -0
- package/docs/api/optics-lens-psf-profile.md +3 -1
- package/docs/api/output-developed-lens-corrections.md +12 -0
- package/docs/api/output-generic-lens-corrections.md +0 -9
- package/llms.txt +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"development-detail.js","sourceRoot":"","sources":["../../src/processing/development-detail.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Development detail stages (#552), both opt-in and off by default:\n *\n * - **Diffraction correction**: a bounded, regularized (Wiener–Tikhonov) deconvolution of the developed linear RGB with the\n * diffraction OTF of an ideal circular pupil at the capture's working f-number. The OTF is zero beyond the cut-off\n * f_c = 1/(λ·N_w), so detail beyond it never reached the sensor; the filter's design gain there is 0 and it cannot, and\n * does not claim to, restore it.\n * - **Sharpening**: an unsharp mask (radius, amount, threshold) on the display-encoded values, after the tone curve and\n * gamut handling and before quantization. It raises edge contrast and creates halos; it adds no optical detail.\n *\n * Development order with these stages: (exposure gain) → demosaic → colour and white balance → diffraction correction\n * (linear) → rendering exposure and tone curve → gamut handling → sRGB transfer → unsharp mask → quantization (encode).\n *\n * Image edges are handled by clamping (edge pixels repeated). Both stages work on a whole in-memory image.\n * @see docs/DIGITAL_OPTICS_FOUNDATION.md for the equations, sources, trade-offs and limits.\n */\n\nimport { encodeSrgbComponent } from \"../color/srgb-transfer.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { InvalidScientificResultError } from \"../core/validation.js\";\nimport { prepareSdrPixelTone, type SdrRenderingProfile } from \"../output/sdr-rendering.js\";\n\n/** Version of the `development-detail` model (diffraction correction and unsharp mask). */\nexport const DEVELOPMENT_DETAIL_MODEL_VERSION = \"0.1.0\" as const;\n\n/** Unsharp mask settings: Gaussian standard deviation in output pixels, gain on the detail signal, and threshold in encoded units [0, 1]. */\nexport interface UnsharpMaskSettings { radiusPixels: number; amount: number; threshold: number }\n/** Diffraction correction settings: design wavelength, Wiener noise-to-signal regularization, gain bound and FIR radius in pixels. */\nexport interface DiffractionCorrectionSettings { wavelengthNm: number; regularization: number; maximumGain: number; kernelRadiusPixels: number }\n\n/** Accepted ranges. Bounds are engineering limits on cost and on noise gain, not quality recommendations. */\nexport const DEVELOPMENT_DETAIL_LIMITS = /* @__PURE__ */ Object.freeze({\n maximumUnsharpRadiusPixels: 8, maximumUnsharpAmount: 5,\n minimumWavelengthNm: 380, maximumWavelengthNm: 780,\n minimumRegularization: 1e-4, maximumRegularization: 1,\n maximumGain: 10, maximumKernelRadiusPixels: 16\n});\n\n/** Third dark ring of the Airy pattern, in units of λ·N (j₁,₃/π, j₁,₃ = 10.1734681…). */\nconst AIRY_THIRD_ZERO_PER_LAMBDA_N = 10.173468135062722 / Math.PI;\n\nfunction finiteIn(value: unknown, name: string, minimum: number, maximum: number, minimumExclusive = false): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || (minimumExclusive ? value <= minimum : value < minimum) || value > maximum) {\n throw new InvalidConfigurationError(name + \" must be a finite number in \" + (minimumExclusive ? \"(\" : \"[\") + minimum + \", \" + maximum + \"].\");\n }\n return value;\n}\n\n/** Validates unsharp mask settings. */\nexport function parseUnsharpMaskSettings(value: UnsharpMaskSettings, path = \"sharpening\"): UnsharpMaskSettings {\n return { radiusPixels: finiteIn(value.radiusPixels, path + \".radiusPixels\", 0, DEVELOPMENT_DETAIL_LIMITS.maximumUnsharpRadiusPixels, true),\n amount: finiteIn(value.amount, path + \".amount\", 0, DEVELOPMENT_DETAIL_LIMITS.maximumUnsharpAmount, true),\n threshold: finiteIn(value.threshold, path + \".threshold\", 0, 1) };\n}\n/** Validates diffraction correction settings. */\nexport function parseDiffractionCorrectionSettings(value: DiffractionCorrectionSettings, path = \"diffractionCorrection\"): DiffractionCorrectionSettings {\n const radius = value.kernelRadiusPixels;\n if (typeof radius !== \"number\" || !Number.isSafeInteger(radius) || radius < 1 || radius > DEVELOPMENT_DETAIL_LIMITS.maximumKernelRadiusPixels) {\n throw new InvalidConfigurationError(path + \".kernelRadiusPixels must be an integer from 1 to \" + DEVELOPMENT_DETAIL_LIMITS.maximumKernelRadiusPixels + \".\");\n }\n return { wavelengthNm: finiteIn(value.wavelengthNm, path + \".wavelengthNm\", DEVELOPMENT_DETAIL_LIMITS.minimumWavelengthNm, DEVELOPMENT_DETAIL_LIMITS.maximumWavelengthNm),\n regularization: finiteIn(value.regularization, path + \".regularization\", DEVELOPMENT_DETAIL_LIMITS.minimumRegularization, DEVELOPMENT_DETAIL_LIMITS.maximumRegularization),\n maximumGain: finiteIn(value.maximumGain, path + \".maximumGain\", 1, DEVELOPMENT_DETAIL_LIMITS.maximumGain), kernelRadiusPixels: radius };\n}\n/** Default FIR radius: the Airy pattern's third dark ring (3.2383·λ·N_w) in pixels, rounded up, within 1..16. */\nexport function defaultDiffractionCorrectionRadiusPixels(workingFNumber: number, wavelengthNm: number, pixelPitchMicrometers: number): number {\n const sites = Math.ceil(AIRY_THIRD_ZERO_PER_LAMBDA_N * wavelengthNm / 1000 * workingFNumber / pixelPitchMicrometers);\n return Math.min(DEVELOPMENT_DETAIL_LIMITS.maximumKernelRadiusPixels, Math.max(1, sites));\n}\n\n/**\n * Incoherent OTF of an ideal, aberration-free circular pupil at normalized frequency s = f/f_c:\n * H(s) = (2/π)(acos s − s·√(1 − s²)) for s < 1, and 0 for s ≥ 1 (MIT OCW 2.71, lectures 21–22; Goodman, §7.3).\n */\nexport function circularPupilDiffractionMtf(normalizedFrequency: number): number {\n const s = Math.abs(normalizedFrequency);\n if (s >= 1) return 0;\n return 2 / Math.PI * (Math.acos(s) - s * Math.sqrt(1 - s * s));\n}\n\n/** A designed diffraction correction filter and what its response does. Frequencies are in cycles per pixel. */\nexport interface DiffractionCorrectionFilter {\n settings: DiffractionCorrectionSettings;\n workingFNumber: number;\n pixelPitchMicrometers: number;\n /** f_c · pitch = pitch/(λ·N_w): the diffraction cut-off. The sampling Nyquist frequency is 0.5. */\n cutoffCyclesPerPixel: number;\n /** Fraction of the Nyquist square |fx|, |fy| ≤ 0.5 lying beyond the cut-off, where the lens transmitted nothing. */\n nyquistAreaBeyondCutoffFraction: number;\n /** Largest gain of the designed (untruncated) response: min(maximumGain, max over s of H(1+α)/(H² + α)). */\n designPeakGain: number;\n /** Largest |response| of the windowed, truncated FIR over a 1/64-cycle grid of the Nyquist square. */\n responsePeakGain: number;\n /**\n * Largest |response| of the FIR at grid frequencies beyond the cut-off (null when the whole Nyquist square is inside it).\n * The design is 0 there; a non-zero value is truncation leakage that passes noise and aliased signal, never lost detail,\n * because the optics delivered no signal at those frequencies.\n */\n responseMaximumBeyondCutoff: number | null;\n /** Row-major (2R+1)² weights summing to 1; weights[(dy + R)(2R + 1) + dx + R]. */\n weights: Float64Array;\n}\n\n/**\n * Designs the bounded Wiener–Tikhonov correction. In frequency (normalized s = ρ/f_c, ρ the radial frequency):\n * G(s) = min(maximumGain, H(s)·(1 + α)/(H(s)² + α)), G(0) = 1, and G(s) = 0 for s ≥ 1,\n * where α is the regularization (an assumed noise-to-signal power ratio, Wiener's K). The response is sampled on an M × M\n * grid (M a power of two ≥ max(64, 4(2R + 1))), inverse transformed, truncated to the (2R + 1)² window with a radial raised\n * cosine taper and renormalized to unit sum. The achieved response is then measured, not assumed.\n */\nexport function designDiffractionCorrectionFilter(input: { workingFNumber: number; pixelPitchMicrometers: number; settings: DiffractionCorrectionSettings }): DiffractionCorrectionFilter {\n const settings = parseDiffractionCorrectionSettings(input.settings);\n const workingFNumber = finiteIn(input.workingFNumber, \"workingFNumber\", 0, 1e4, true), pitch = finiteIn(input.pixelPitchMicrometers, \"pixelPitchMicrometers\", 0, 1e4, true);\n const cutoff = pitch / (settings.wavelengthNm / 1000 * workingFNumber), alpha = settings.regularization, bound = settings.maximumGain;\n const gainAt = (rho: number): number => {\n const h = circularPupilDiffractionMtf(rho / cutoff);\n return h === 0 ? 0 : Math.min(bound, h * (1 + alpha) / (h * h + alpha));\n };\n const R = settings.kernelRadiusPixels, size = 2 * R + 1;\n let M = 64;\n while (M < 4 * size) M *= 2;\n // A(ky, x) = Σ_kx G cos(2π kx x/M); h(x, y) = (1/M²) Σ_ky cos(2π ky y/M) A(ky, x). G is even in each axis, so h is real and even.\n const cosTable = new Float64Array(M * (R + 1));\n for (let k = 0; k < M; k++) for (let x = 0; x <= R; x++) cosTable[k * (R + 1) + x] = Math.cos(2 * Math.PI * k * x / M);\n const A = new Float64Array(M * (R + 1));\n for (let ky = 0; ky < M; ky++) {\n const fy = (ky < M / 2 ? ky : ky - M) / M;\n for (let kx = 0; kx < M; kx++) {\n const fx = (kx < M / 2 ? kx : kx - M) / M, g = gainAt(Math.hypot(fx, fy));\n if (g === 0) continue;\n for (let x = 0; x <= R; x++) A[ky * (R + 1) + x]! += g * cosTable[kx * (R + 1) + x]!;\n }\n }\n const quarter = new Float64Array((R + 1) * (R + 1));\n for (let y = 0; y <= R; y++) for (let x = 0; x <= R; x++) {\n let sum = 0;\n for (let ky = 0; ky < M; ky++) sum += cosTable[ky * (R + 1) + y]! * A[ky * (R + 1) + x]!;\n const r = Math.hypot(x, y), taper = r < R + 1 ? 0.5 * (1 + Math.cos(Math.PI * r / (R + 1))) : 0;\n quarter[y * (R + 1) + x] = sum / (M * M) * taper;\n }\n const weights = new Float64Array(size * size);\n let total = 0;\n for (let dy = -R; dy <= R; dy++) for (let dx = -R; dx <= R; dx++) {\n const w = quarter[Math.abs(dy) * (R + 1) + Math.abs(dx)]!;\n weights[(dy + R) * size + dx + R] = w; total += w;\n }\n if (!(total > 0) || !Number.isFinite(total)) throw new InvalidScientificResultError(\"Diffraction correction filter has no finite DC response.\");\n for (let i = 0; i < weights.length; i++) weights[i] = weights[i]! / total;\n let designPeakGain = 0;\n for (let i = 0; i <= 4096; i++) designPeakGain = Math.max(designPeakGain, gainAt(i / 4096 * cutoff));\n let responsePeakGain = 0, beyond: number | null = null, beyondCount = 0;\n const GRID = 64;\n for (let iy = 0; iy <= GRID / 2; iy++) for (let ix = 0; ix <= GRID / 2; ix++) {\n const fx = ix / GRID, fy = iy / GRID, response = Math.abs(evaluateDiffractionCorrectionResponse(weights, R, fx, fy));\n responsePeakGain = Math.max(responsePeakGain, response);\n if (Math.hypot(fx, fy) >= cutoff) beyond = Math.max(beyond ?? 0, response);\n }\n const AREA = 256;\n for (let iy = 0; iy < AREA; iy++) for (let ix = 0; ix < AREA; ix++) if (Math.hypot((ix + 0.5) / (2 * AREA), (iy + 0.5) / (2 * AREA)) >= cutoff) beyondCount++;\n return { settings, workingFNumber, pixelPitchMicrometers: pitch, cutoffCyclesPerPixel: cutoff, nyquistAreaBeyondCutoffFraction: beyondCount / (AREA * AREA),\n designPeakGain, responsePeakGain, responseMaximumBeyondCutoff: beyond, weights };\n}\n/** Frequency response Σ w(x, y)·cos(2π(fx·x + fy·y)) of a centred (2R + 1)² FIR at (fx, fy) cycles per pixel. */\nexport function evaluateDiffractionCorrectionResponse(weights: Float64Array, radius: number, fx: number, fy: number): number {\n const size = 2 * radius + 1;\n let sum = 0;\n for (let dy = -radius; dy <= radius; dy++) for (let dx = -radius; dx <= radius; dx++) sum += weights[(dy + radius) * size + dx + radius]! * Math.cos(2 * Math.PI * (fx * dx + fy * dy));\n return sum;\n}\n\n/** What the correction did to the linear samples. */\nexport interface DiffractionCorrectionDiagnostics {\n /** Corrected samples below 0 (ringing below black). They are clipped by the later gamut handling. */\n negativeSampleCount: number;\n /** Corrected samples above 1 (above the RAW white level). */\n aboveWhiteSampleCount: number;\n}\n/**\n * Applies the FIR to interleaved linear RGB (width × height × 3), each channel separately, edges clamped. Returns new samples.\n */\nexport function applyDiffractionCorrection(rgb: Float64Array, width: number, height: number, filter: Pick<DiffractionCorrectionFilter, \"weights\" | \"settings\">):\n { samples: Float64Array; diagnostics: DiffractionCorrectionDiagnostics } {\n if (rgb.length !== width * height * 3) throw new InvalidConfigurationError(\"Diffraction correction raster size mismatch.\");\n const R = filter.settings.kernelRadiusPixels, size = 2 * R + 1, w = filter.weights, out = new Float64Array(rgb.length);\n const xs = new Int32Array(width + 2 * R);\n for (let i = 0; i < xs.length; i++) xs[i] = Math.min(width - 1, Math.max(0, i - R)) * 3;\n let negative = 0, above = 0;\n for (let y = 0; y < height; y++) {\n const o = y * width * 3;\n for (let dy = -R; dy <= R; dy++) {\n const row = Math.min(height - 1, Math.max(0, y + dy)) * width * 3, wr = (dy + R) * size;\n for (let dx = 0; dx < size; dx++) {\n const weight = w[wr + dx]!;\n if (weight === 0) continue;\n for (let x = 0; x < width; x++) {\n const s = row + xs[x + dx]!, d = o + 3 * x;\n out[d] = out[d]! + weight * rgb[s]!; out[d + 1] = out[d + 1]! + weight * rgb[s + 1]!; out[d + 2] = out[d + 2]! + weight * rgb[s + 2]!;\n }\n }\n }\n }\n for (let i = 0; i < out.length; i++) {\n const v = out[i]!;\n if (!Number.isFinite(v)) throw new InvalidScientificResultError(\"Diffraction correction produced a non-finite sample.\");\n if (v < 0) negative++; else if (v > 1) above++;\n }\n return { samples: out, diagnostics: { negativeSampleCount: negative, aboveWhiteSampleCount: above } };\n}\n\n/** Normalized Gaussian weights exp(−i²/(2σ²)), i = −r..r with r = ⌈3σ⌉. */\nexport function unsharpMaskKernel(radiusPixels: number): Float64Array {\n const r = Math.ceil(3 * radiusPixels), k = new Float64Array(2 * r + 1);\n let total = 0;\n for (let i = -r; i <= r; i++) { const v = Math.exp(-i * i / (2 * radiusPixels * radiusPixels)); k[i + r] = v; total += v; }\n for (let i = 0; i < k.length; i++) k[i] = k[i]! / total;\n return k;\n}\n/** What the unsharp mask did. Counts are samples (one per channel). */\nexport interface UnsharpMaskDiagnostics {\n /** Half-width of the separable Gaussian, ⌈3σ⌉ pixels. */\n kernelRadiusPixels: number;\n /** Samples changed by the mask (|detail| ≥ threshold and detail ≠ 0). */\n sharpenedSampleCount: number;\n /** Samples left unchanged because 0 < |detail| < threshold. */\n thresholdHeldSampleCount: number;\n /** Sharpened samples clipped at 0 or 1 (the halo did not fit in the code range). */\n clippedLowSampleCount: number;\n clippedHighSampleCount: number;\n /** Largest increase and decrease amount·detail before clipping, in encoded units: the halo strength. */\n maximumIncrease: number;\n maximumDecrease: number;\n}\n/**\n * Unsharp mask on interleaved encoded RGB in [0, 1] (each channel separately, edges clamped):\n * d = x − (G_σ ∗ x); y = x + amount·d where |d| ≥ threshold, else y = x; then y is clipped to [0, 1].\n * Returns new samples.\n */\nexport function applyUnsharpMask(encoded: Float64Array, width: number, height: number, settings: UnsharpMaskSettings):\n { samples: Float64Array; diagnostics: UnsharpMaskDiagnostics } {\n const s = parseUnsharpMaskSettings(settings);\n if (encoded.length !== width * height * 3) throw new InvalidConfigurationError(\"Unsharp mask raster size mismatch.\");\n const k = unsharpMaskKernel(s.radiusPixels), r = (k.length - 1) / 2, horizontal = new Float64Array(encoded.length), blurred = new Float64Array(encoded.length);\n for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {\n const d = (y * width + x) * 3;\n let a = 0, b = 0, c = 0;\n for (let i = -r; i <= r; i++) {\n const sx = (y * width + Math.min(width - 1, Math.max(0, x + i))) * 3, w = k[i + r]!;\n a += w * encoded[sx]!; b += w * encoded[sx + 1]!; c += w * encoded[sx + 2]!;\n }\n horizontal[d] = a; horizontal[d + 1] = b; horizontal[d + 2] = c;\n }\n for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {\n const d = (y * width + x) * 3;\n let a = 0, b = 0, c = 0;\n for (let i = -r; i <= r; i++) {\n const sy = (Math.min(height - 1, Math.max(0, y + i)) * width + x) * 3, w = k[i + r]!;\n a += w * horizontal[sy]!; b += w * horizontal[sy + 1]!; c += w * horizontal[sy + 2]!;\n }\n blurred[d] = a; blurred[d + 1] = b; blurred[d + 2] = c;\n }\n const out = new Float64Array(encoded.length);\n let sharpened = 0, held = 0, low = 0, high = 0, increase = 0, decrease = 0;\n for (let i = 0; i < encoded.length; i++) {\n const x = encoded[i]!, detail = x - blurred[i]!;\n if (detail === 0 || Math.abs(detail) < s.threshold) { if (detail !== 0) held++; out[i] = x; continue; }\n const change = s.amount * detail;\n let v = x + change;\n sharpened++;\n if (change > increase) increase = change;\n if (-change > decrease) decrease = -change;\n if (v < 0) { v = 0; low++; } else if (v > 1) { v = 1; high++; }\n out[i] = v;\n }\n return { samples: out, diagnostics: { kernelRadiusPixels: r, sharpenedSampleCount: sharpened, thresholdHeldSampleCount: held, clippedLowSampleCount: low,\n clippedHighSampleCount: high, maximumIncrease: increase, maximumDecrease: decrease } };\n}\n\n/** SDR counters in the shape of the SDR rendering diagnostics. */\nexport interface DetailSdrCounts { negative: number; above: number; changed: number; low: number; high: number }\n/**\n * SDR rendering with an unsharp mask between the sRGB transfer and quantization. Per pixel it runs the reference renderer's\n * operations in its order (−0 → +0, rendering exposure 2^EV with reference white 1, the shared tone operator, gamut\n * handling, sRGB transfer); the whole encoded image is then sharpened and rounded to nearest (ties up).\n */\nexport function renderSdrWithUnsharpMask(rgb: Float64Array, width: number, height: number, profile: SdrRenderingProfile, settings: UnsharpMaskSettings):\n { codes: Uint8Array | Uint16Array; counts: DetailSdrCounts; sharpening: UnsharpMaskDiagnostics } {\n if (rgb.length !== width * height * 3) throw new InvalidConfigurationError(\"SDR raster size mismatch.\");\n const scale = 2 ** profile.renderingExposureEv, tone = prepareSdrPixelTone(profile), scratch = new Float64Array(3), encoded = new Float64Array(rgb.length);\n if (!Number.isFinite(scale) || scale <= 0) throw new InvalidConfigurationError(\"Rendering scale is unrepresentable.\");\n const reject = profile.gamutHandling === \"reject-out-of-range\", counts: DetailSdrCounts = { negative: 0, above: 0, changed: 0, low: 0, high: 0 };\n for (let i = 0; i < rgb.length; i += 3) {\n const r = rgb[i]!, g = rgb[i + 1]!, b = rgb[i + 2]!;\n const er = (r === 0 ? 0 : r) * scale, eg = (g === 0 ? 0 : g) * scale, eb = (b === 0 ? 0 : b) * scale;\n if (!Number.isFinite(er) || !Number.isFinite(eg) || !Number.isFinite(eb)) throw new InvalidScientificResultError(\"Rendering exposure produced a non-finite sample.\");\n tone(er, eg, eb, scratch);\n for (let c = 0; c < 3; c++) {\n const exposed = c === 0 ? er : c === 1 ? eg : eb;\n if (exposed < 0) counts.negative++;\n if (exposed > 1) counts.above++;\n let mapped = scratch[c]!;\n if (mapped !== exposed) counts.changed++;\n if (mapped === 0) mapped = 0;\n if (mapped < 0 || mapped > 1) {\n if (reject) throw new InvalidConfigurationError(\"Tone output exceeds the declared SDR gamut range.\");\n if (mapped < 0) { counts.low++; mapped = 0; } else { counts.high++; mapped = 1; }\n }\n encoded[i + c] = encodeSrgbComponent(mapped);\n }\n }\n const sharpened = applyUnsharpMask(encoded, width, height, settings), maximum = 2 ** profile.bitDepth - 1;\n const codes = profile.bitDepth === 8 ? new Uint8Array(rgb.length) : new Uint16Array(rgb.length);\n for (let i = 0; i < codes.length; i++) codes[i] = Math.round(sharpened.samples[i]! * maximum);\n return { codes, counts, sharpening: sharpened.diagnostics };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"development-detail.js","sourceRoot":"","sources":["../../src/processing/development-detail.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Development detail stages (#552), both opt-in and off by default:\n *\n * - **Diffraction correction**: a bounded, regularized (Wiener–Tikhonov) deconvolution of the developed linear RGB with the\n * diffraction OTF of an ideal circular pupil at the capture's working f-number. The OTF is zero beyond the cut-off\n * f_c = 1/(λ·N_w), so detail beyond it never reached the sensor; the filter's design gain there is 0 and it cannot, and\n * does not claim to, restore it.\n * - **Sharpening**: an unsharp mask (radius, amount, threshold) on the display-encoded values, after the tone curve and\n * gamut handling and before quantization. It raises edge contrast and creates halos; it adds no optical detail.\n *\n * Development order with these stages: (exposure gain) → demosaic → colour and white balance → diffraction correction\n * (linear) → rendering exposure and tone curve → gamut handling → sRGB transfer → unsharp mask → quantization (encode).\n *\n * Image edges are handled by clamping (edge pixels repeated). Both stages need the whole image; since #571 they also run row by\n * row in place (`correctDiffractionInPlace`, `renderSdrWithUnsharpMaskInPlace`), with the same sums in the same order.\n * @see docs/DIGITAL_OPTICS_FOUNDATION.md for the equations, sources, trade-offs and limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { InvalidScientificResultError } from \"../core/validation.js\";\nimport { renderSdrRunInto, type SdrPixelCounts } from \"../output/native-capture-sdr.js\";\nimport { prepareSdrPixelTone, type SdrRenderingProfile } from \"../output/sdr-rendering.js\";\n\n/** Version of the `development-detail` model (diffraction correction and unsharp mask). */\nexport const DEVELOPMENT_DETAIL_MODEL_VERSION = \"0.1.0\" as const;\n\n/** Unsharp mask settings: Gaussian standard deviation in output pixels, gain on the detail signal, and threshold in encoded units [0, 1]. */\nexport interface UnsharpMaskSettings { radiusPixels: number; amount: number; threshold: number }\n/** Diffraction correction settings: design wavelength, Wiener noise-to-signal regularization, gain bound and FIR radius in pixels. */\nexport interface DiffractionCorrectionSettings { wavelengthNm: number; regularization: number; maximumGain: number; kernelRadiusPixels: number }\n\n/** Accepted ranges. Bounds are engineering limits on cost and on noise gain, not quality recommendations. */\nexport const DEVELOPMENT_DETAIL_LIMITS = /* @__PURE__ */ Object.freeze({\n maximumUnsharpRadiusPixels: 8, maximumUnsharpAmount: 5,\n minimumWavelengthNm: 380, maximumWavelengthNm: 780,\n minimumRegularization: 1e-4, maximumRegularization: 1,\n maximumGain: 10, maximumKernelRadiusPixels: 16\n});\n\n/** Third dark ring of the Airy pattern, in units of λ·N (j₁,₃/π, j₁,₃ = 10.1734681…). */\nconst AIRY_THIRD_ZERO_PER_LAMBDA_N = 10.173468135062722 / Math.PI;\n\nfunction finiteIn(value: unknown, name: string, minimum: number, maximum: number, minimumExclusive = false): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || (minimumExclusive ? value <= minimum : value < minimum) || value > maximum) {\n throw new InvalidConfigurationError(name + \" must be a finite number in \" + (minimumExclusive ? \"(\" : \"[\") + minimum + \", \" + maximum + \"].\");\n }\n return value;\n}\n\n/** Validates unsharp mask settings. */\nexport function parseUnsharpMaskSettings(value: UnsharpMaskSettings, path = \"sharpening\"): UnsharpMaskSettings {\n return { radiusPixels: finiteIn(value.radiusPixels, path + \".radiusPixels\", 0, DEVELOPMENT_DETAIL_LIMITS.maximumUnsharpRadiusPixels, true),\n amount: finiteIn(value.amount, path + \".amount\", 0, DEVELOPMENT_DETAIL_LIMITS.maximumUnsharpAmount, true),\n threshold: finiteIn(value.threshold, path + \".threshold\", 0, 1) };\n}\n/** Validates diffraction correction settings. */\nexport function parseDiffractionCorrectionSettings(value: DiffractionCorrectionSettings, path = \"diffractionCorrection\"): DiffractionCorrectionSettings {\n const radius = value.kernelRadiusPixels;\n if (typeof radius !== \"number\" || !Number.isSafeInteger(radius) || radius < 1 || radius > DEVELOPMENT_DETAIL_LIMITS.maximumKernelRadiusPixels) {\n throw new InvalidConfigurationError(path + \".kernelRadiusPixels must be an integer from 1 to \" + DEVELOPMENT_DETAIL_LIMITS.maximumKernelRadiusPixels + \".\");\n }\n return { wavelengthNm: finiteIn(value.wavelengthNm, path + \".wavelengthNm\", DEVELOPMENT_DETAIL_LIMITS.minimumWavelengthNm, DEVELOPMENT_DETAIL_LIMITS.maximumWavelengthNm),\n regularization: finiteIn(value.regularization, path + \".regularization\", DEVELOPMENT_DETAIL_LIMITS.minimumRegularization, DEVELOPMENT_DETAIL_LIMITS.maximumRegularization),\n maximumGain: finiteIn(value.maximumGain, path + \".maximumGain\", 1, DEVELOPMENT_DETAIL_LIMITS.maximumGain), kernelRadiusPixels: radius };\n}\n/** Default FIR radius: the Airy pattern's third dark ring (3.2383·λ·N_w) in pixels, rounded up, within 1..16. */\nexport function defaultDiffractionCorrectionRadiusPixels(workingFNumber: number, wavelengthNm: number, pixelPitchMicrometers: number): number {\n const sites = Math.ceil(AIRY_THIRD_ZERO_PER_LAMBDA_N * wavelengthNm / 1000 * workingFNumber / pixelPitchMicrometers);\n return Math.min(DEVELOPMENT_DETAIL_LIMITS.maximumKernelRadiusPixels, Math.max(1, sites));\n}\n\n/**\n * Incoherent OTF of an ideal, aberration-free circular pupil at normalized frequency s = f/f_c:\n * H(s) = (2/π)(acos s − s·√(1 − s²)) for s < 1, and 0 for s ≥ 1 (MIT OCW 2.71, lectures 21–22; Goodman, §7.3).\n */\nexport function circularPupilDiffractionMtf(normalizedFrequency: number): number {\n const s = Math.abs(normalizedFrequency);\n if (s >= 1) return 0;\n return 2 / Math.PI * (Math.acos(s) - s * Math.sqrt(1 - s * s));\n}\n\n/** A designed diffraction correction filter and what its response does. Frequencies are in cycles per pixel. */\nexport interface DiffractionCorrectionFilter {\n settings: DiffractionCorrectionSettings;\n workingFNumber: number;\n pixelPitchMicrometers: number;\n /** f_c · pitch = pitch/(λ·N_w): the diffraction cut-off. The sampling Nyquist frequency is 0.5. */\n cutoffCyclesPerPixel: number;\n /** Fraction of the Nyquist square |fx|, |fy| ≤ 0.5 lying beyond the cut-off, where the lens transmitted nothing. */\n nyquistAreaBeyondCutoffFraction: number;\n /** Largest gain of the designed (untruncated) response: min(maximumGain, max over s of H(1+α)/(H² + α)). */\n designPeakGain: number;\n /** Largest |response| of the windowed, truncated FIR over a 1/64-cycle grid of the Nyquist square. */\n responsePeakGain: number;\n /**\n * Largest |response| of the FIR at grid frequencies beyond the cut-off (null when the whole Nyquist square is inside it).\n * The design is 0 there; a non-zero value is truncation leakage that passes noise and aliased signal, never lost detail,\n * because the optics delivered no signal at those frequencies.\n */\n responseMaximumBeyondCutoff: number | null;\n /** Row-major (2R+1)² weights summing to 1; weights[(dy + R)(2R + 1) + dx + R]. */\n weights: Float64Array;\n}\n\n/**\n * Designs the bounded Wiener–Tikhonov correction. In frequency (normalized s = ρ/f_c, ρ the radial frequency):\n * G(s) = min(maximumGain, H(s)·(1 + α)/(H(s)² + α)), G(0) = 1, and G(s) = 0 for s ≥ 1,\n * where α is the regularization (an assumed noise-to-signal power ratio, Wiener's K). The response is sampled on an M × M\n * grid (M a power of two ≥ max(64, 4(2R + 1))), inverse transformed, truncated to the (2R + 1)² window with a radial raised\n * cosine taper and renormalized to unit sum. The achieved response is then measured, not assumed.\n */\nexport function designDiffractionCorrectionFilter(input: { workingFNumber: number; pixelPitchMicrometers: number; settings: DiffractionCorrectionSettings }): DiffractionCorrectionFilter {\n const settings = parseDiffractionCorrectionSettings(input.settings);\n const workingFNumber = finiteIn(input.workingFNumber, \"workingFNumber\", 0, 1e4, true), pitch = finiteIn(input.pixelPitchMicrometers, \"pixelPitchMicrometers\", 0, 1e4, true);\n const cutoff = pitch / (settings.wavelengthNm / 1000 * workingFNumber), alpha = settings.regularization, bound = settings.maximumGain;\n const gainAt = (rho: number): number => {\n const h = circularPupilDiffractionMtf(rho / cutoff);\n return h === 0 ? 0 : Math.min(bound, h * (1 + alpha) / (h * h + alpha));\n };\n const R = settings.kernelRadiusPixels, size = 2 * R + 1;\n let M = 64;\n while (M < 4 * size) M *= 2;\n // A(ky, x) = Σ_kx G cos(2π kx x/M); h(x, y) = (1/M²) Σ_ky cos(2π ky y/M) A(ky, x). G is even in each axis, so h is real and even.\n const cosTable = new Float64Array(M * (R + 1));\n for (let k = 0; k < M; k++) for (let x = 0; x <= R; x++) cosTable[k * (R + 1) + x] = Math.cos(2 * Math.PI * k * x / M);\n const A = new Float64Array(M * (R + 1));\n for (let ky = 0; ky < M; ky++) {\n const fy = (ky < M / 2 ? ky : ky - M) / M;\n for (let kx = 0; kx < M; kx++) {\n const fx = (kx < M / 2 ? kx : kx - M) / M, g = gainAt(Math.hypot(fx, fy));\n if (g === 0) continue;\n for (let x = 0; x <= R; x++) A[ky * (R + 1) + x]! += g * cosTable[kx * (R + 1) + x]!;\n }\n }\n const quarter = new Float64Array((R + 1) * (R + 1));\n for (let y = 0; y <= R; y++) for (let x = 0; x <= R; x++) {\n let sum = 0;\n for (let ky = 0; ky < M; ky++) sum += cosTable[ky * (R + 1) + y]! * A[ky * (R + 1) + x]!;\n const r = Math.hypot(x, y), taper = r < R + 1 ? 0.5 * (1 + Math.cos(Math.PI * r / (R + 1))) : 0;\n quarter[y * (R + 1) + x] = sum / (M * M) * taper;\n }\n const weights = new Float64Array(size * size);\n let total = 0;\n for (let dy = -R; dy <= R; dy++) for (let dx = -R; dx <= R; dx++) {\n const w = quarter[Math.abs(dy) * (R + 1) + Math.abs(dx)]!;\n weights[(dy + R) * size + dx + R] = w; total += w;\n }\n if (!(total > 0) || !Number.isFinite(total)) throw new InvalidScientificResultError(\"Diffraction correction filter has no finite DC response.\");\n for (let i = 0; i < weights.length; i++) weights[i] = weights[i]! / total;\n let designPeakGain = 0;\n for (let i = 0; i <= 4096; i++) designPeakGain = Math.max(designPeakGain, gainAt(i / 4096 * cutoff));\n let responsePeakGain = 0, beyond: number | null = null, beyondCount = 0;\n const GRID = 64;\n for (let iy = 0; iy <= GRID / 2; iy++) for (let ix = 0; ix <= GRID / 2; ix++) {\n const fx = ix / GRID, fy = iy / GRID, response = Math.abs(evaluateDiffractionCorrectionResponse(weights, R, fx, fy));\n responsePeakGain = Math.max(responsePeakGain, response);\n if (Math.hypot(fx, fy) >= cutoff) beyond = Math.max(beyond ?? 0, response);\n }\n const AREA = 256;\n for (let iy = 0; iy < AREA; iy++) for (let ix = 0; ix < AREA; ix++) if (Math.hypot((ix + 0.5) / (2 * AREA), (iy + 0.5) / (2 * AREA)) >= cutoff) beyondCount++;\n return { settings, workingFNumber, pixelPitchMicrometers: pitch, cutoffCyclesPerPixel: cutoff, nyquistAreaBeyondCutoffFraction: beyondCount / (AREA * AREA),\n designPeakGain, responsePeakGain, responseMaximumBeyondCutoff: beyond, weights };\n}\n/** Frequency response Σ w(x, y)·cos(2π(fx·x + fy·y)) of a centred (2R + 1)² FIR at (fx, fy) cycles per pixel. */\nexport function evaluateDiffractionCorrectionResponse(weights: Float64Array, radius: number, fx: number, fy: number): number {\n const size = 2 * radius + 1;\n let sum = 0;\n for (let dy = -radius; dy <= radius; dy++) for (let dx = -radius; dx <= radius; dx++) sum += weights[(dy + radius) * size + dx + radius]! * Math.cos(2 * Math.PI * (fx * dx + fy * dy));\n return sum;\n}\n\n/** What the correction did to the linear samples. */\nexport interface DiffractionCorrectionDiagnostics {\n /** Corrected samples below 0 (ringing below black). They are clipped by the later gamut handling. */\n negativeSampleCount: number;\n /** Corrected samples above 1 (above the RAW white level). */\n aboveWhiteSampleCount: number;\n}\n/**\n * Applies the FIR to interleaved linear RGB (width × height × 3), each channel separately, edges clamped. Returns new samples.\n */\nexport function applyDiffractionCorrection(rgb: Float64Array, width: number, height: number, filter: Pick<DiffractionCorrectionFilter, \"weights\" | \"settings\">):\n { samples: Float64Array; diagnostics: DiffractionCorrectionDiagnostics } {\n if (rgb.length !== width * height * 3) throw new InvalidConfigurationError(\"Diffraction correction raster size mismatch.\");\n const samples = Float64Array.from(rgb);\n return { samples, diagnostics: drainDetailRows(correctDiffractionInPlace(samples, width, height, filter)) };\n}\n/** Runs a row-by-row detail stage to its end and returns its result. */\nexport function drainDetailRows<T>(rows: Generator<number, T, void>): T {\n let step = rows.next();\n while (!step.done) step = rows.next();\n return step.value;\n}\n/**\n * `applyDiffractionCorrection` in place, one output row per step (#571); each step yields the number of rows done. Output row y\n * reads input rows y − R … y + R, so it waits in a ring of R + 1 rows and replaces input row y once row y + R is done. Every sample\n * is the same sum in the same order as in a separate output image, so the result is bit-identical, with one image in memory\n * instead of two. `rgb` must hold width × height pixels.\n */\nexport function* correctDiffractionInPlace(rgb: Float64Array, width: number, height: number, filter: Pick<DiffractionCorrectionFilter, \"weights\" | \"settings\">):\n Generator<number, DiffractionCorrectionDiagnostics, void> {\n const R = filter.settings.kernelRadiusPixels, size = 2 * R + 1, w = filter.weights, rowLength = width * 3, ring = new Float64Array((R + 1) * rowLength);\n const xs = new Int32Array(width + 2 * R);\n for (let i = 0; i < xs.length; i++) xs[i] = Math.min(width - 1, Math.max(0, i - R)) * 3;\n let negative = 0, above = 0;\n for (let y = 0; y <= height + R; y++) {\n // Output row y − R − 1 holds the slot of row y; input row y − R − 1 is read by no later output row, so it takes its place.\n const o = (y % (R + 1)) * rowLength;\n if (y > R) rgb.set(ring.subarray(o, o + rowLength), (y - R - 1) * rowLength);\n if (y >= height) continue;\n ring.fill(0, o, o + rowLength);\n for (let dy = -R; dy <= R; dy++) {\n const row = Math.min(height - 1, Math.max(0, y + dy)) * rowLength, wr = (dy + R) * size;\n for (let dx = 0; dx < size; dx++) {\n const weight = w[wr + dx]!;\n if (weight === 0) continue;\n for (let x = 0; x < width; x++) {\n const s = row + xs[x + dx]!, d = o + 3 * x;\n ring[d] = ring[d]! + weight * rgb[s]!; ring[d + 1] = ring[d + 1]! + weight * rgb[s + 1]!; ring[d + 2] = ring[d + 2]! + weight * rgb[s + 2]!;\n }\n }\n }\n for (let i = o; i < o + rowLength; i++) {\n const v = ring[i]!;\n if (!Number.isFinite(v)) throw new InvalidScientificResultError(\"Diffraction correction produced a non-finite sample.\");\n if (v < 0) negative++; else if (v > 1) above++;\n }\n yield y + 1;\n }\n return { negativeSampleCount: negative, aboveWhiteSampleCount: above };\n}\n\n/** Normalized Gaussian weights exp(−i²/(2σ²)), i = −r..r with r = ⌈3σ⌉. */\nexport function unsharpMaskKernel(radiusPixels: number): Float64Array {\n const r = Math.ceil(3 * radiusPixels), k = new Float64Array(2 * r + 1);\n let total = 0;\n for (let i = -r; i <= r; i++) { const v = Math.exp(-i * i / (2 * radiusPixels * radiusPixels)); k[i + r] = v; total += v; }\n for (let i = 0; i < k.length; i++) k[i] = k[i]! / total;\n return k;\n}\n/** What the unsharp mask did. Counts are samples (one per channel). */\nexport interface UnsharpMaskDiagnostics {\n /** Half-width of the separable Gaussian, ⌈3σ⌉ pixels. */\n kernelRadiusPixels: number;\n /** Samples changed by the mask (|detail| ≥ threshold and detail ≠ 0). */\n sharpenedSampleCount: number;\n /** Samples left unchanged because 0 < |detail| < threshold. */\n thresholdHeldSampleCount: number;\n /** Sharpened samples clipped at 0 or 1 (the halo did not fit in the code range). */\n clippedLowSampleCount: number;\n clippedHighSampleCount: number;\n /** Largest increase and decrease amount·detail before clipping, in encoded units: the halo strength. */\n maximumIncrease: number;\n maximumDecrease: number;\n}\n/**\n * Unsharp mask on interleaved encoded RGB in [0, 1] (each channel separately, edges clamped):\n * d = x − (G_σ ∗ x); y = x + amount·d where |d| ≥ threshold, else y = x; then y is clipped to [0, 1].\n * Returns new samples.\n */\nexport function applyUnsharpMask(encoded: Float64Array, width: number, height: number, settings: UnsharpMaskSettings):\n { samples: Float64Array; diagnostics: UnsharpMaskDiagnostics } {\n const s = parseUnsharpMaskSettings(settings);\n if (encoded.length !== width * height * 3) throw new InvalidConfigurationError(\"Unsharp mask raster size mismatch.\");\n const samples = new Float64Array(encoded.length);\n return { samples, diagnostics: drainDetailRows(unsharpMaskRows(encoded, width, height, s, samples)) };\n}\n/**\n * The unsharp mask one output row per step (#571); each step yields the number of rows done. The horizontal Gaussian pass of\n * each input row is kept in a ring of 2r + 1 rows, and `prepareRow(y)`, when given, runs once on input row y before it is\n * first read (`renderSdrWithUnsharpMaskInPlace` encodes the row there). Output row y goes to `out`: the clipped value, or\n * Math.round(value · scale) with a `scale`. Every sum is the same, in the same order, as in whole-image passes, so the\n * result is bit-identical, with 2r + 1 rows of working memory instead of three images. `settings` must be parsed and the\n * raster sizes must match.\n */\nexport function* unsharpMaskRows(encoded: Float64Array, width: number, height: number, settings: UnsharpMaskSettings, out: Float64Array | Uint8Array | Uint16Array,\n scale?: number, prepareRow?: (y: number) => void): Generator<number, UnsharpMaskDiagnostics, void> {\n const k = unsharpMaskKernel(settings.radiusPixels), r = (k.length - 1) / 2, span = 2 * r + 1, rowLength = width * 3, ring = new Float64Array(span * rowLength);\n const amount = settings.amount, threshold = settings.threshold;\n let sharpened = 0, held = 0, low = 0, high = 0, increase = 0, decrease = 0, ready = 0;\n for (let y = 0; y < height; y++) {\n // Rows up to y + r, prepared and horizontally blurred.\n for (const last = Math.min(height - 1, y + r); ready <= last; ready++) {\n prepareRow?.(ready);\n const source = ready * rowLength, slot = (ready % span) * rowLength;\n for (let x = 0; x < width; x++) {\n let a = 0, b = 0, c = 0;\n for (let i = -r; i <= r; i++) {\n const sx = source + Math.min(width - 1, Math.max(0, x + i)) * 3, w = k[i + r]!;\n a += w * encoded[sx]!; b += w * encoded[sx + 1]!; c += w * encoded[sx + 2]!;\n }\n ring[slot + 3 * x] = a; ring[slot + 3 * x + 1] = b; ring[slot + 3 * x + 2] = c;\n }\n }\n const o = y * rowLength;\n for (let x = 0; x < width; x++) {\n let a = 0, b = 0, c = 0;\n for (let i = -r; i <= r; i++) {\n const sy = (Math.min(height - 1, Math.max(0, y + i)) % span) * rowLength + 3 * x, w = k[i + r]!;\n a += w * ring[sy]!; b += w * ring[sy + 1]!; c += w * ring[sy + 2]!;\n }\n for (let channel = 0; channel < 3; channel++) {\n const index = o + 3 * x + channel, value = encoded[index]!, detail = value - (channel === 0 ? a : channel === 1 ? b : c);\n let v = value;\n if (detail === 0 || Math.abs(detail) < threshold) { if (detail !== 0) held++; }\n else {\n const change = amount * detail;\n v = value + change;\n sharpened++;\n if (change > increase) increase = change;\n if (-change > decrease) decrease = -change;\n if (v < 0) { v = 0; low++; } else if (v > 1) { v = 1; high++; }\n }\n out[index] = scale === undefined ? v : Math.round(v * scale);\n }\n }\n yield y + 1;\n }\n return { kernelRadiusPixels: r, sharpenedSampleCount: sharpened, thresholdHeldSampleCount: held, clippedLowSampleCount: low,\n clippedHighSampleCount: high, maximumIncrease: increase, maximumDecrease: decrease };\n}\n\n/** SDR counters in the shape of the SDR rendering diagnostics. */\nexport interface DetailSdrCounts { negative: number; above: number; changed: number; low: number; high: number }\n/**\n * SDR rendering with an unsharp mask between the sRGB transfer and quantization. Per pixel it runs the reference renderer's\n * operations in its order (−0 → +0, rendering exposure 2^EV with reference white 1, the shared tone operator, gamut\n * handling, sRGB transfer); the whole encoded image is then sharpened and rounded to nearest (ties up).\n */\nexport function renderSdrWithUnsharpMask(rgb: Float64Array, width: number, height: number, profile: SdrRenderingProfile, settings: UnsharpMaskSettings):\n { codes: Uint8Array | Uint16Array; counts: DetailSdrCounts; sharpening: UnsharpMaskDiagnostics } {\n if (rgb.length !== width * height * 3) throw new InvalidConfigurationError(\"SDR raster size mismatch.\");\n const { codes, counts: { negative, above, changed, low, high }, sharpening } =\n drainDetailRows(renderSdrWithUnsharpMaskInPlace(Float64Array.from(rgb), width, height, profile, parseUnsharpMaskSettings(settings)));\n return { codes, counts: { negative, above, changed, low, high }, sharpening };\n}\n/**\n * `renderSdrWithUnsharpMask` one output row per step (#571), encoding each row of `rgb` in place just before the mask first reads\n * it (`rgb` then holds the encoded values). Bit-identical to the whole-image function, with no second image in memory. `settings`\n * must be parsed and `rgb` must hold width × height pixels.\n */\nexport function* renderSdrWithUnsharpMaskInPlace(rgb: Float64Array, width: number, height: number, profile: SdrRenderingProfile, settings: UnsharpMaskSettings):\n Generator<number, { codes: Uint8Array | Uint16Array; counts: SdrPixelCounts; sharpening: UnsharpMaskDiagnostics }, void> {\n const scale = 2 ** profile.renderingExposureEv, tone = prepareSdrPixelTone(profile), scratch = new Float64Array(3);\n if (!Number.isFinite(scale) || scale <= 0) throw new InvalidConfigurationError(\"Rendering scale is unrepresentable.\");\n const counts: SdrPixelCounts = { negative: 0, above: 0, changed: 0, low: 0, high: 0, outOfGamut: false };\n // The native SDR kernel per row, unquantized (maximum 0), in place: the reference renderer's operations in its order.\n const encodeRow = (y: number): void => {\n renderSdrRunInto(rgb, y * width * 3, width, profile, tone, scale, 0, rgb, y * width * 3, scratch, counts);\n if (counts.outOfGamut) throw new InvalidConfigurationError(\"Tone output exceeds the declared SDR gamut range.\");\n };\n const codes = profile.bitDepth === 8 ? new Uint8Array(rgb.length) : new Uint16Array(rgb.length);\n const sharpening = yield* unsharpMaskRows(rgb, width, height, settings, codes, 2 ** profile.bitDepth - 1, encodeRow);\n return { codes, counts, sharpening };\n}\n"]}
|
|
@@ -12,48 +12,10 @@
|
|
|
12
12
|
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
13
13
|
import { parseEvidenceList } from "../core/evidence-provenance.js";
|
|
14
14
|
import { InvalidScientificInputError, requirePositiveInteger } from "../core/validation.js";
|
|
15
|
-
import { requireInputKeys,
|
|
15
|
+
import { requireInputKeys, rejectUnknownVariantFields, requireFixedFieldsWhenPresent, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, requireConfigFinite as requireFinite, parseConfigScientificStatus as parseScientificStatus, requireConfigFiniteAboveZero as requirePositiveFinite, requireConfigFiniteAtLeastZero as requireNonNegativeFinite } from "../core/record-validation.js";
|
|
16
|
+
import { parseUncertainty } from "../optics/lens-psf-profile.js";
|
|
17
|
+
import { positiveModulo } from "../optics/complex-pupil-psf.js";
|
|
16
18
|
export const SCENE_ILLUMINATION_TEMPORAL_PROFILE_SCHEMA_VERSION = "0.1.0";
|
|
17
|
-
function requireRecord(value, path, allowedKeys) {
|
|
18
|
-
if (typeof value !== "object" ||
|
|
19
|
-
value === null ||
|
|
20
|
-
Array.isArray(value)) {
|
|
21
|
-
throw new InvalidConfigurationError(path + " must be an object.");
|
|
22
|
-
}
|
|
23
|
-
if (allowedKeys !== null)
|
|
24
|
-
rejectUnknownFields(value, allowedKeys, path);
|
|
25
|
-
return value;
|
|
26
|
-
}
|
|
27
|
-
function requireNonEmptyString(value, path) {
|
|
28
|
-
if (typeof value !== "string" ||
|
|
29
|
-
value.trim().length === 0) {
|
|
30
|
-
throw new InvalidConfigurationError(path + " must be a non-empty string.");
|
|
31
|
-
}
|
|
32
|
-
return value.trim();
|
|
33
|
-
}
|
|
34
|
-
function requireFinite(value, path) {
|
|
35
|
-
if (typeof value !== "number" ||
|
|
36
|
-
!Number.isFinite(value)) {
|
|
37
|
-
throw new InvalidConfigurationError(path + " must be finite.");
|
|
38
|
-
}
|
|
39
|
-
return value;
|
|
40
|
-
}
|
|
41
|
-
function requirePositiveFinite(value, path) {
|
|
42
|
-
const parsed = requireFinite(value, path);
|
|
43
|
-
if (parsed <= 0) {
|
|
44
|
-
throw new InvalidConfigurationError(path +
|
|
45
|
-
" must be greater than zero.");
|
|
46
|
-
}
|
|
47
|
-
return parsed;
|
|
48
|
-
}
|
|
49
|
-
function requireNonNegativeFinite(value, path) {
|
|
50
|
-
const parsed = requireFinite(value, path);
|
|
51
|
-
if (parsed < 0) {
|
|
52
|
-
throw new InvalidConfigurationError(path +
|
|
53
|
-
" must be greater than or equal to zero.");
|
|
54
|
-
}
|
|
55
|
-
return parsed;
|
|
56
|
-
}
|
|
57
19
|
function requireReusableNumericEvidence(value, path) {
|
|
58
20
|
const evidence = parseEvidenceList(value, path);
|
|
59
21
|
if (!evidence.some((entry) => entry.reuseStatus ===
|
|
@@ -65,31 +27,6 @@ function requireReusableNumericEvidence(value, path) {
|
|
|
65
27
|
}
|
|
66
28
|
return evidence;
|
|
67
29
|
}
|
|
68
|
-
function parseScientificStatus(value, path) {
|
|
69
|
-
if (value !== "calibrated" &&
|
|
70
|
-
value !== "approximation") {
|
|
71
|
-
throw new InvalidConfigurationError(path + " is invalid.");
|
|
72
|
-
}
|
|
73
|
-
return value;
|
|
74
|
-
}
|
|
75
|
-
function parseUncertainty(value, path) {
|
|
76
|
-
const record = requireRecord(value, path, null);
|
|
77
|
-
rejectUnknownVariantFields(record, "kind", UNCERTAINTY_VARIANT_FIELDS, path);
|
|
78
|
-
if (record.kind === "relative") {
|
|
79
|
-
return {
|
|
80
|
-
kind: "relative",
|
|
81
|
-
fraction: requireNonNegativeFinite(record.fraction, path + ".fraction"),
|
|
82
|
-
basis: requireNonEmptyString(record.basis, path + ".basis")
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
if (record.kind === "not-quantified") {
|
|
86
|
-
return {
|
|
87
|
-
kind: "not-quantified",
|
|
88
|
-
limitation: requireNonEmptyString(record.limitation, path + ".limitation")
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
throw new InvalidConfigurationError(path + ".kind is invalid.");
|
|
92
|
-
}
|
|
93
30
|
function parseRegistrationUncertainty(value, path) {
|
|
94
31
|
const record = requireRecord(value, path, null);
|
|
95
32
|
rejectUnknownVariantFields(record, "kind", { "absolute-seconds": ["kind", "plusMinusSeconds", "basis"], "not-quantified": ["kind", "limitation"] }, path);
|
|
@@ -394,12 +331,6 @@ function interpolateWaveform(samples, timeSeconds) {
|
|
|
394
331
|
return last
|
|
395
332
|
.relativeMagnitudeMultiplier;
|
|
396
333
|
}
|
|
397
|
-
function positiveModulo(value, modulus) {
|
|
398
|
-
const remainder = value % modulus;
|
|
399
|
-
return remainder < 0
|
|
400
|
-
? remainder + modulus
|
|
401
|
-
: remainder;
|
|
402
|
-
}
|
|
403
334
|
function evaluateWaveform(waveform, waveformTimeSeconds) {
|
|
404
335
|
if (waveform.kind ===
|
|
405
336
|
"aperiodic-relative-multiplier") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"illumination-temporal.js","sourceRoot":"","sources":["../../src/schema/illumination-temporal.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Time-varying light sources, such as flicker or a pulsed light.\n *\n * A temporal profile sits on top of an existing illumination profile. Each binding multiplies\n * one source by a relative waveform over time. The base source magnitude and spectrum still\n * apply, and sources with no binding stay constant. This module parses the profile, evaluates\n * a waveform at one capture time, and integrates it over an exposure window.\n * @see docs/SCENE_RADIANCE_AND_ILLUMINATION.md for equations, coordinate/unit conventions, blockers\n * and support limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport {\n InvalidScientificInputError,\n requirePositiveInteger\n} from \"../core/validation.js\";\nimport type {\n CaptureExposureWindows\n} from \"../sensor/exposure-window.js\";\nimport type {\n SceneIlluminationProfile,\n SceneIlluminationUncertainty\n} from \"./illumination.js\";\nimport { requireInputKeys, rejectUnknownFields, rejectUnknownVariantFields, UNCERTAINTY_VARIANT_FIELDS, requireFixedFieldsWhenPresent } from \"../core/record-validation.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport const SCENE_ILLUMINATION_TEMPORAL_PROFILE_SCHEMA_VERSION =\n \"0.1.0\" as const;\n\nexport type SceneIlluminationTemporalScientificStatus =\n | \"calibrated\"\n | \"approximation\";\n\nexport interface SceneIlluminationTemporalWaveformSample {\n timeSecondsFromWaveformReference: number;\n relativeMagnitudeMultiplier: number;\n}\n\ninterface SceneIlluminationTemporalWaveformBase {\n waveformId: string;\n timeUnit: \"s\";\n scientificStatus:\n SceneIlluminationTemporalScientificStatus;\n uncertainty: SceneIlluminationUncertainty;\n evidence: readonly EvidenceProvenance[];\n interpolation: \"piecewise-linear\";\n samples:\n readonly SceneIlluminationTemporalWaveformSample[];\n}\n\nexport type SceneIlluminationTemporalWaveform =\n | (SceneIlluminationTemporalWaveformBase & {\n kind:\n \"aperiodic-relative-multiplier\";\n outsideSupportBehavior: \"zero\";\n })\n | (SceneIlluminationTemporalWaveformBase & {\n kind:\n \"periodic-relative-multiplier\";\n periodSeconds: number;\n endpointContinuityRequired: true;\n });\n\nexport type SceneIlluminationTemporalRegistrationUncertainty =\n | {\n kind: \"absolute-seconds\";\n plusMinusSeconds: number;\n basis: string;\n }\n | {\n kind: \"not-quantified\";\n limitation: string;\n };\n\nexport interface SceneIlluminationTemporalSourceBinding {\n bindingId: string;\n sourceId: string;\n waveformId: string;\n captureTimeReference:\n \"first-opening-boundary-phase\";\n /**\n * The capture time at which the waveform's own t=0 falls.\n *\n * waveformTime = captureTime - waveformTimeZeroSecondsFromCaptureReference\n */\n waveformTimeZeroSecondsFromCaptureReference:\n number;\n scientificStatus:\n SceneIlluminationTemporalScientificStatus;\n timingUncertainty:\n SceneIlluminationTemporalRegistrationUncertainty;\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface SceneIlluminationTemporalProfile {\n schemaVersion:\n typeof SCENE_ILLUMINATION_TEMPORAL_PROFILE_SCHEMA_VERSION;\n profileId: string;\n sceneId: string;\n illuminationProfileId: string;\n evidence: readonly EvidenceProvenance[];\n waveforms:\n readonly SceneIlluminationTemporalWaveform[];\n sourceBindings:\n readonly SceneIlluminationTemporalSourceBinding[];\n baseIlluminationProfileRemainsAuthoritative:\n true;\n sensorReadoutTimingUsedAsExposureTiming:\n false;\n automaticExposurePolicyIncluded: false;\n}\n\nexport interface EvaluateSceneIlluminationTemporalMultiplierInput {\n illuminationProfile:\n SceneIlluminationProfile;\n temporalProfile:\n SceneIlluminationTemporalProfile;\n sourceId: string;\n captureTimeSecondsFromReference: number;\n}\n\nexport interface SceneIlluminationTemporalMultiplierEvaluation {\n sourceId: string;\n sourceEnabled: boolean;\n temporalProfileId: string;\n bindingId: string;\n waveformId: string;\n captureTimeReference:\n \"first-opening-boundary-phase\";\n captureTimeSecondsFromReference: number;\n waveformTimeSecondsFromWaveformReference:\n number;\n waveformKind:\n SceneIlluminationTemporalWaveform[\"kind\"];\n relativeMagnitudeMultiplier: number;\n effectiveRelativeMagnitudeMultiplier:\n number;\n sourceMagnitudeApplied: false;\n materialTransportApplied: false;\n sceneRadianceCalculated: false;\n sensorReadoutTimingUsed: false;\n automaticExposureResolved: false;\n}\n\nexport interface IntegrateSceneIlluminationTemporalMultiplierInput {\n illuminationProfile:\n SceneIlluminationProfile;\n temporalProfile:\n SceneIlluminationTemporalProfile;\n sourceId: string;\n exposureWindows: CaptureExposureWindows;\n sampleIndex: number;\n temporalSampleCount: number;\n}\n\nexport interface SceneIlluminationTemporalIntegrationNode {\n temporalSampleIndex: number;\n localExposurePhase: number;\n captureTimeSecondsFromReference: number;\n waveformTimeSecondsFromWaveformReference:\n number;\n relativeMagnitudeMultiplier: number;\n effectiveRelativeMagnitudeMultiplier:\n number;\n normalizedTimeWeight: number;\n timeMeasureSeconds: number;\n}\n\nexport interface SceneIlluminationTemporalExposureIntegration {\n sourceId: string;\n sourceEnabled: boolean;\n temporalProfileId: string;\n bindingId: string;\n waveformId: string;\n timeReference:\n \"first-opening-boundary-phase\";\n localExposureWindow: {\n startSecondsFromCaptureReference: number;\n endSecondsFromCaptureReference: number;\n durationSeconds: number;\n };\n quadratureScheme: \"uniform-midpoint\";\n temporalSampleCount: number;\n nodes:\n readonly SceneIlluminationTemporalIntegrationNode[];\n averageRelativeMagnitudeMultiplier:\n number;\n integratedRelativeMagnitudeSeconds:\n number;\n averageEffectiveRelativeMagnitudeMultiplier:\n number;\n integratedEffectiveRelativeMagnitudeSeconds:\n number;\n sourceMagnitudeApplied: false;\n materialTransportApplied: false;\n sceneRadianceCalculated: false;\n sensorReadoutTimingUsed: false;\n automaticExposureResolved: false;\n convergenceErrorEstimated: false;\n}\n\nfunction requireRecord(\n value: unknown,\n path: string,\n allowedKeys: readonly string[] | null\n): UnknownRecord {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be an object.\"\n );\n }\n if (allowedKeys !== null) rejectUnknownFields(value, allowedKeys, path);\n return value as UnknownRecord;\n}\n\nfunction requireNonEmptyString(\n value: unknown,\n path: string\n): string {\n if (\n typeof value !== \"string\" ||\n value.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n path + \" must be a non-empty string.\"\n );\n }\n return value.trim();\n}\n\nfunction requireFinite(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be finite.\"\n );\n }\n return value;\n}\n\nfunction requirePositiveFinite(\n value: unknown,\n path: string\n): number {\n const parsed = requireFinite(\n value,\n path\n );\n if (parsed <= 0) {\n throw new InvalidConfigurationError(\n path +\n \" must be greater than zero.\"\n );\n }\n return parsed;\n}\n\nfunction requireNonNegativeFinite(\n value: unknown,\n path: string\n): number {\n const parsed = requireFinite(\n value,\n path\n );\n if (parsed < 0) {\n throw new InvalidConfigurationError(\n path +\n \" must be greater than or equal to zero.\"\n );\n }\n return parsed;\n}\n\nfunction requireReusableNumericEvidence(\n value: unknown,\n path: string\n): readonly EvidenceProvenance[] {\n const evidence = parseEvidenceList(\n value,\n path\n );\n if (\n !evidence.some(\n (entry) =>\n entry.reuseStatus ===\n \"reusable-data\" ||\n entry.reuseStatus ===\n \"photivra-owned\"\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must contain reusable-data or photivra-owned evidence because the waveform embeds reusable numeric data.\"\n );\n }\n return evidence;\n}\n\nfunction parseScientificStatus(\n value: unknown,\n path: string\n): SceneIlluminationTemporalScientificStatus {\n if (\n value !== \"calibrated\" &&\n value !== \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value;\n}\n\nfunction parseUncertainty(\n value: unknown,\n path: string\n): SceneIlluminationUncertainty {\n const record = requireRecord(\n value,\n path, null\n );\n rejectUnknownVariantFields(record, \"kind\", UNCERTAINTY_VARIANT_FIELDS, path);\n if (record.kind === \"relative\") {\n return {\n kind: \"relative\",\n fraction:\n requireNonNegativeFinite(\n record.fraction,\n path + \".fraction\"\n ),\n basis: requireNonEmptyString(\n record.basis,\n path + \".basis\"\n )\n };\n }\n if (record.kind === \"not-quantified\") {\n return {\n kind: \"not-quantified\",\n limitation:\n requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseRegistrationUncertainty(\n value: unknown,\n path: string\n): SceneIlluminationTemporalRegistrationUncertainty {\n const record = requireRecord(\n value,\n path, null\n );\n rejectUnknownVariantFields(record, \"kind\", { \"absolute-seconds\": [\"kind\", \"plusMinusSeconds\", \"basis\"], \"not-quantified\": [\"kind\", \"limitation\"] }, path);\n if (\n record.kind ===\n \"absolute-seconds\"\n ) {\n return {\n kind: \"absolute-seconds\",\n plusMinusSeconds:\n requireNonNegativeFinite(\n record.plusMinusSeconds,\n path +\n \".plusMinusSeconds\"\n ),\n basis: requireNonEmptyString(\n record.basis,\n path + \".basis\"\n )\n };\n }\n if (record.kind === \"not-quantified\") {\n return {\n kind: \"not-quantified\",\n limitation:\n requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseWaveformSamples(\n value: unknown,\n path: string\n): readonly SceneIlluminationTemporalWaveformSample[] {\n if (\n !Array.isArray(value) ||\n value.length < 2\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must contain at least two samples.\"\n );\n }\n\n let previous =\n Number.NEGATIVE_INFINITY;\n return value.map((entry, index) => {\n const samplePath =\n path + \"[\" + index + \"]\";\n const sample = requireRecord(\n entry,\n samplePath, [\"timeSecondsFromWaveformReference\", \"relativeMagnitudeMultiplier\"]\n );\n const time =\n requireNonNegativeFinite(\n sample\n .timeSecondsFromWaveformReference,\n samplePath +\n \".timeSecondsFromWaveformReference\"\n );\n if (time <= previous) {\n throw new InvalidConfigurationError(\n path +\n \" times must be strictly increasing.\"\n );\n }\n previous = time;\n return {\n timeSecondsFromWaveformReference:\n time,\n relativeMagnitudeMultiplier:\n requireNonNegativeFinite(\n sample\n .relativeMagnitudeMultiplier,\n samplePath +\n \".relativeMagnitudeMultiplier\"\n )\n };\n });\n}\n\nconst WAVEFORM_BASE_FIELDS = [\"kind\", \"waveformId\", \"timeUnit\", \"scientificStatus\", \"uncertainty\", \"evidence\", \"interpolation\", \"samples\"] as const;\n\nfunction parseWaveform(\n value: unknown,\n path: string\n): SceneIlluminationTemporalWaveform {\n const record = requireRecord(\n value,\n path, null\n );\n rejectUnknownVariantFields(record, \"kind\", {\n \"aperiodic-relative-multiplier\": [...WAVEFORM_BASE_FIELDS, \"outsideSupportBehavior\"],\n \"periodic-relative-multiplier\": [...WAVEFORM_BASE_FIELDS, \"periodSeconds\", \"endpointContinuityRequired\"]\n }, path);\n if (record.timeUnit !== \"s\") {\n throw new InvalidConfigurationError(\n path + '.timeUnit must be \"s\".'\n );\n }\n if (\n record.interpolation !==\n \"piecewise-linear\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.interpolation must be \"piecewise-linear\".'\n );\n }\n\n const waveformId =\n requireNonEmptyString(\n record.waveformId,\n path + \".waveformId\"\n );\n const scientificStatus =\n parseScientificStatus(\n record.scientificStatus,\n path + \".scientificStatus\"\n );\n const uncertainty =\n parseUncertainty(\n record.uncertainty,\n path + \".uncertainty\"\n );\n if (\n scientificStatus === \"calibrated\" &&\n uncertainty.kind !== \"relative\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \" calibrated waveform data requires quantified relative uncertainty.\"\n );\n }\n const evidence =\n requireReusableNumericEvidence(\n record.evidence,\n path + \".evidence\"\n );\n const samples =\n parseWaveformSamples(\n record.samples,\n path + \".samples\"\n );\n\n if (\n samples[0]!\n .timeSecondsFromWaveformReference !==\n 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \".samples must begin at waveform-local t=0.\"\n );\n }\n\n if (\n record.kind ===\n \"aperiodic-relative-multiplier\"\n ) {\n if (\n record.outsideSupportBehavior !==\n \"zero\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.outsideSupportBehavior must be \"zero\".'\n );\n }\n return {\n kind:\n \"aperiodic-relative-multiplier\",\n waveformId,\n timeUnit: \"s\",\n scientificStatus,\n uncertainty,\n evidence,\n interpolation:\n \"piecewise-linear\",\n samples,\n outsideSupportBehavior:\n \"zero\"\n };\n }\n\n if (\n record.kind ===\n \"periodic-relative-multiplier\"\n ) {\n const periodSeconds =\n requirePositiveFinite(\n record.periodSeconds,\n path + \".periodSeconds\"\n );\n const last =\n samples[samples.length - 1]!;\n if (\n last\n .timeSecondsFromWaveformReference !==\n periodSeconds\n ) {\n throw new InvalidConfigurationError(\n path +\n \".samples must end exactly at periodSeconds.\"\n );\n }\n if (\n samples[0]!\n .relativeMagnitudeMultiplier !==\n last.relativeMagnitudeMultiplier\n ) {\n throw new InvalidConfigurationError(\n path +\n \" periodic endpoint multipliers must match.\"\n );\n }\n if (\n record.endpointContinuityRequired !==\n true\n ) {\n throw new InvalidConfigurationError(\n path +\n \".endpointContinuityRequired must be true.\"\n );\n }\n return {\n kind:\n \"periodic-relative-multiplier\",\n waveformId,\n timeUnit: \"s\",\n scientificStatus,\n uncertainty,\n evidence,\n interpolation:\n \"piecewise-linear\",\n samples,\n periodSeconds,\n endpointContinuityRequired:\n true\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseSourceBinding(\n value: unknown,\n path: string\n): SceneIlluminationTemporalSourceBinding {\n const record = requireRecord(\n value,\n path, [\"captureTimeReference\", \"scientificStatus\", \"timingUncertainty\", \"bindingId\", \"sourceId\", \"waveformId\", \"waveformTimeZeroSecondsFromCaptureReference\", \"evidence\"]\n );\n if (\n record.captureTimeReference !==\n \"first-opening-boundary-phase\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.captureTimeReference must be \"first-opening-boundary-phase\".'\n );\n }\n\n const scientificStatus =\n parseScientificStatus(\n record.scientificStatus,\n path + \".scientificStatus\"\n );\n const timingUncertainty =\n parseRegistrationUncertainty(\n record.timingUncertainty,\n path + \".timingUncertainty\"\n );\n if (\n scientificStatus === \"calibrated\" &&\n timingUncertainty.kind !==\n \"absolute-seconds\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \" calibrated waveform registration requires quantified absolute timing uncertainty.\"\n );\n }\n\n return {\n bindingId:\n requireNonEmptyString(\n record.bindingId,\n path + \".bindingId\"\n ),\n sourceId:\n requireNonEmptyString(\n record.sourceId,\n path + \".sourceId\"\n ),\n waveformId:\n requireNonEmptyString(\n record.waveformId,\n path + \".waveformId\"\n ),\n captureTimeReference:\n \"first-opening-boundary-phase\",\n waveformTimeZeroSecondsFromCaptureReference:\n requireFinite(\n record\n .waveformTimeZeroSecondsFromCaptureReference,\n path +\n \".waveformTimeZeroSecondsFromCaptureReference\"\n ),\n scientificStatus,\n timingUncertainty,\n evidence: parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\n/** Fixed flags the parser writes; a parsed profile may carry them back in unchanged. */\nconst TEMPORAL_PROFILE_FIXED_FIELDS = {\n baseIlluminationProfileRemainsAuthoritative: true, sensorReadoutTimingUsedAsExposureTiming: false,\n automaticExposurePolicyIncluded: false\n} as const;\n\n/**\n * Parses a time-varying illumination profile that sits on top of one existing\n * illumination profile.\n *\n * The base source magnitude and spectrum still apply. Each binding multiplies one\n * source by one relative waveform over time. Sources with no binding stay constant.\n */\nexport function parseSceneIlluminationTemporalProfile(\n value: unknown\n): SceneIlluminationTemporalProfile {\n const record = requireRecord(\n value,\n \"sceneIlluminationTemporalProfile\", [\"schemaVersion\", \"waveforms\", \"sourceBindings\", \"profileId\", \"sceneId\", \"illuminationProfileId\", \"evidence\", ...Object.keys(TEMPORAL_PROFILE_FIXED_FIELDS)]\n );\n requireFixedFieldsWhenPresent(record, TEMPORAL_PROFILE_FIXED_FIELDS, \"sceneIlluminationTemporalProfile\");\n if (\n record.schemaVersion !==\n SCENE_ILLUMINATION_TEMPORAL_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'sceneIlluminationTemporalProfile.schemaVersion must be \"' +\n SCENE_ILLUMINATION_TEMPORAL_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n if (!Array.isArray(record.waveforms)) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationTemporalProfile.waveforms must be an array.\"\n );\n }\n if (\n !Array.isArray(record.sourceBindings)\n ) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationTemporalProfile.sourceBindings must be an array.\"\n );\n }\n\n const waveforms =\n record.waveforms.map(\n (entry, index) =>\n parseWaveform(\n entry,\n \"sceneIlluminationTemporalProfile.waveforms[\" +\n index +\n \"]\"\n )\n );\n const waveformIds =\n waveforms.map(\n (entry) => entry.waveformId\n );\n if (\n new Set(waveformIds).size !==\n waveformIds.length\n ) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationTemporalProfile.waveforms[].waveformId must not contain duplicates.\"\n );\n }\n\n const sourceBindings =\n record.sourceBindings.map(\n (entry, index) =>\n parseSourceBinding(\n entry,\n \"sceneIlluminationTemporalProfile.sourceBindings[\" +\n index +\n \"]\"\n )\n );\n const bindingIds =\n sourceBindings.map(\n (entry) => entry.bindingId\n );\n if (\n new Set(bindingIds).size !==\n bindingIds.length\n ) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationTemporalProfile.sourceBindings[].bindingId must not contain duplicates.\"\n );\n }\n const sourceIds =\n sourceBindings.map(\n (entry) => entry.sourceId\n );\n if (\n new Set(sourceIds).size !==\n sourceIds.length\n ) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationTemporalProfile supports at most one temporal binding per sourceId in schema 0.1.0.\"\n );\n }\n const waveformIdSet =\n new Set(waveformIds);\n for (const binding of sourceBindings) {\n if (\n !waveformIdSet.has(\n binding.waveformId\n )\n ) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationTemporalProfile source binding references an unknown waveformId.\"\n );\n }\n }\n\n return {\n schemaVersion:\n SCENE_ILLUMINATION_TEMPORAL_PROFILE_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"sceneIlluminationTemporalProfile.profileId\"\n ),\n sceneId:\n requireNonEmptyString(\n record.sceneId,\n \"sceneIlluminationTemporalProfile.sceneId\"\n ),\n illuminationProfileId:\n requireNonEmptyString(\n record.illuminationProfileId,\n \"sceneIlluminationTemporalProfile.illuminationProfileId\"\n ),\n evidence: parseEvidenceList(\n record.evidence,\n \"sceneIlluminationTemporalProfile.evidence\"\n ),\n waveforms,\n sourceBindings,\n baseIlluminationProfileRemainsAuthoritative:\n true,\n sensorReadoutTimingUsedAsExposureTiming:\n false,\n automaticExposurePolicyIncluded:\n false\n };\n}\n\nfunction requireProfileBindings(\n illuminationProfile:\n SceneIlluminationProfile,\n temporalProfile:\n SceneIlluminationTemporalProfile\n): void {\n if (\n temporalProfile.sceneId !==\n illuminationProfile.sceneId\n ) {\n throw new InvalidScientificInputError(\n \"Temporal illumination profile sceneId must match the illumination profile.\"\n );\n }\n if (\n temporalProfile\n .illuminationProfileId !==\n illuminationProfile.profileId\n ) {\n throw new InvalidScientificInputError(\n \"Temporal illumination profile illuminationProfileId must match the supplied illumination profile.\"\n );\n }\n\n const knownSourceIds =\n new Set(\n illuminationProfile.sources.map(\n (entry) => entry.sourceId\n )\n );\n for (\n const binding of\n temporalProfile.sourceBindings\n ) {\n if (\n !knownSourceIds.has(\n binding.sourceId\n )\n ) {\n throw new InvalidScientificInputError(\n \"Temporal illumination source binding references a sourceId that is not declared by the illumination profile.\"\n );\n }\n }\n}\n\nfunction resolveSourceAndTemporalBinding(\n illuminationProfile:\n SceneIlluminationProfile,\n temporalProfile:\n SceneIlluminationTemporalProfile,\n sourceId: string\n): {\n source:\n SceneIlluminationProfile[\"sources\"][number];\n binding:\n SceneIlluminationTemporalSourceBinding;\n waveform:\n SceneIlluminationTemporalWaveform;\n} {\n requireProfileBindings(\n illuminationProfile,\n temporalProfile\n );\n\n const source =\n illuminationProfile.sources.find(\n (entry) =>\n entry.sourceId === sourceId\n );\n if (source === undefined) {\n throw new InvalidScientificInputError(\n \"sourceId is not declared by the supplied illumination profile.\"\n );\n }\n\n const binding =\n temporalProfile.sourceBindings.find(\n (entry) =>\n entry.sourceId === sourceId\n );\n if (binding === undefined) {\n throw new InvalidScientificInputError(\n \"Time-varying source evaluation requires an explicit source waveform-to-capture registration.\"\n );\n }\n\n const waveform =\n temporalProfile.waveforms.find(\n (entry) =>\n entry.waveformId ===\n binding.waveformId\n );\n if (waveform === undefined) {\n throw new InvalidScientificInputError(\n \"Temporal source binding waveformId is not declared by the temporal profile.\"\n );\n }\n\n return {\n source,\n binding,\n waveform\n };\n}\n\nfunction interpolateWaveform(\n samples:\n readonly SceneIlluminationTemporalWaveformSample[],\n timeSeconds: number\n): number {\n const first = samples[0]!;\n const last =\n samples[samples.length - 1]!;\n\n if (\n timeSeconds ===\n first.timeSecondsFromWaveformReference\n ) {\n return first\n .relativeMagnitudeMultiplier;\n }\n if (\n timeSeconds ===\n last.timeSecondsFromWaveformReference\n ) {\n return last\n .relativeMagnitudeMultiplier;\n }\n\n for (\n let index = 1;\n index < samples.length;\n index += 1\n ) {\n const right = samples[index]!;\n if (\n timeSeconds <\n right\n .timeSecondsFromWaveformReference\n ) {\n const left =\n samples[index - 1]!;\n const span =\n right\n .timeSecondsFromWaveformReference -\n left\n .timeSecondsFromWaveformReference;\n const phase =\n (timeSeconds -\n left\n .timeSecondsFromWaveformReference) /\n span;\n return (\n left\n .relativeMagnitudeMultiplier +\n phase *\n (right\n .relativeMagnitudeMultiplier -\n left\n .relativeMagnitudeMultiplier)\n );\n }\n }\n\n return last\n .relativeMagnitudeMultiplier;\n}\n\nfunction positiveModulo(\n value: number,\n modulus: number\n): number {\n const remainder = value % modulus;\n return remainder < 0\n ? remainder + modulus\n : remainder;\n}\n\nfunction evaluateWaveform(\n waveform:\n SceneIlluminationTemporalWaveform,\n waveformTimeSeconds: number\n): number {\n if (\n waveform.kind ===\n \"aperiodic-relative-multiplier\"\n ) {\n const last =\n waveform.samples[\n waveform.samples.length - 1\n ]!;\n if (\n waveformTimeSeconds < 0 ||\n waveformTimeSeconds >\n last\n .timeSecondsFromWaveformReference\n ) {\n return 0;\n }\n return interpolateWaveform(\n waveform.samples,\n waveformTimeSeconds\n );\n }\n\n const periodicTime =\n positiveModulo(\n waveformTimeSeconds,\n waveform.periodSeconds\n );\n return interpolateWaveform(\n waveform.samples,\n periodicTime\n );\n}\n\n/**\n * Returns one registered source's time-varying multiplier at one capture time.\n *\n * Capture time is in seconds from the first opening boundary of the exposure. Sensor\n * readout timing is never used in place of capture time.\n */\nexport function evaluateSceneIlluminationTemporalMultiplier(\n input:\n EvaluateSceneIlluminationTemporalMultiplierInput\n): SceneIlluminationTemporalMultiplierEvaluation {\n requireInputKeys(input, \"evaluateSceneIlluminationTemporalMultiplier\", [\"illuminationProfile\", \"temporalProfile\", \"sourceId\", \"captureTimeSecondsFromReference\"]);\n if (\n typeof input.sourceId !== \"string\" ||\n input.sourceId.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n \"sourceId must be a non-empty string.\"\n );\n }\n if (\n typeof input\n .captureTimeSecondsFromReference !==\n \"number\" ||\n !Number.isFinite(\n input\n .captureTimeSecondsFromReference\n )\n ) {\n throw new InvalidScientificInputError(\n \"captureTimeSecondsFromReference must be finite.\"\n );\n }\n\n const {\n source,\n binding,\n waveform\n } =\n resolveSourceAndTemporalBinding(\n input.illuminationProfile,\n input.temporalProfile,\n input.sourceId\n );\n\n const waveformTimeSeconds =\n input\n .captureTimeSecondsFromReference -\n binding\n .waveformTimeZeroSecondsFromCaptureReference;\n const multiplier =\n evaluateWaveform(\n waveform,\n waveformTimeSeconds\n );\n\n return {\n sourceId: source.sourceId,\n sourceEnabled: source.enabled,\n temporalProfileId:\n input.temporalProfile.profileId,\n bindingId: binding.bindingId,\n waveformId: waveform.waveformId,\n captureTimeReference:\n \"first-opening-boundary-phase\",\n captureTimeSecondsFromReference:\n input\n .captureTimeSecondsFromReference,\n waveformTimeSecondsFromWaveformReference:\n waveformTimeSeconds,\n waveformKind: waveform.kind,\n relativeMagnitudeMultiplier:\n multiplier,\n effectiveRelativeMagnitudeMultiplier:\n source.enabled ? multiplier : 0,\n sourceMagnitudeApplied: false,\n materialTransportApplied: false,\n sceneRadianceCalculated: false,\n sensorReadoutTimingUsed: false,\n automaticExposureResolved: false\n };\n}\n\n/**\n * Integrates one source's time-varying multiplier over one local exposure window\n * (from sensor/exposure-window), using the deterministic midpoint rule.\n *\n * It integrates only the relative modulation over time. It does not apply source\n * magnitude, scene light transport, optics, sensor response or metering policy.\n */\nexport function integrateSceneIlluminationTemporalMultiplierOverExposureWindow(\n input:\n IntegrateSceneIlluminationTemporalMultiplierInput\n): SceneIlluminationTemporalExposureIntegration {\n requireInputKeys(input, \"integrateSceneIlluminationTemporalMultiplierOverExposureWindow\", [\"illuminationProfile\", \"temporalProfile\", \"sourceId\", \"exposureWindows\", \"sampleIndex\", \"temporalSampleCount\"]);\n requirePositiveInteger(\n \"temporalSampleCount\",\n input.temporalSampleCount\n );\n if (\n !Number.isSafeInteger(\n input.sampleIndex\n ) ||\n input.sampleIndex < 0\n ) {\n throw new InvalidScientificInputError(\n \"sampleIndex must be a non-negative safe integer.\"\n );\n }\n if (\n input.exposureWindows\n .timeReference !==\n \"first-opening-boundary-phase\"\n ) {\n throw new InvalidScientificInputError(\n \"Exposure windows must use the first-opening-boundary-phase time reference.\"\n );\n }\n\n const window =\n input.exposureWindows.samples[\n input.sampleIndex\n ];\n if (window === undefined) {\n throw new InvalidScientificInputError(\n \"sampleIndex is outside exposureWindows.samples.\"\n );\n }\n\n const context =\n resolveSourceAndTemporalBinding(\n input.illuminationProfile,\n input.temporalProfile,\n input.sourceId\n );\n const durationSeconds =\n window.localExposureDurationSeconds;\n const normalizedTimeWeight =\n 1 / input.temporalSampleCount;\n const timeMeasureSeconds =\n durationSeconds /\n input.temporalSampleCount;\n\n let averageMultiplier = 0;\n let integratedMultiplierSeconds =\n 0;\n let averageEffectiveMultiplier =\n 0;\n let integratedEffectiveMultiplierSeconds =\n 0;\n\n const nodes = Array.from(\n {\n length:\n input.temporalSampleCount\n },\n (_, temporalSampleIndex) => {\n const localExposurePhase =\n (temporalSampleIndex + 0.5) /\n input.temporalSampleCount;\n const captureTimeSeconds =\n window\n .startOffsetSecondsFromOpeningReference +\n localExposurePhase *\n durationSeconds;\n const evaluated =\n evaluateSceneIlluminationTemporalMultiplier(\n {\n illuminationProfile:\n input.illuminationProfile,\n temporalProfile:\n input.temporalProfile,\n sourceId: input.sourceId,\n captureTimeSecondsFromReference:\n captureTimeSeconds\n }\n );\n\n averageMultiplier +=\n evaluated\n .relativeMagnitudeMultiplier *\n normalizedTimeWeight;\n integratedMultiplierSeconds +=\n evaluated\n .relativeMagnitudeMultiplier *\n timeMeasureSeconds;\n averageEffectiveMultiplier +=\n evaluated\n .effectiveRelativeMagnitudeMultiplier *\n normalizedTimeWeight;\n integratedEffectiveMultiplierSeconds +=\n evaluated\n .effectiveRelativeMagnitudeMultiplier *\n timeMeasureSeconds;\n\n return {\n temporalSampleIndex,\n localExposurePhase,\n captureTimeSecondsFromReference:\n captureTimeSeconds,\n waveformTimeSecondsFromWaveformReference:\n evaluated\n .waveformTimeSecondsFromWaveformReference,\n relativeMagnitudeMultiplier:\n evaluated\n .relativeMagnitudeMultiplier,\n effectiveRelativeMagnitudeMultiplier:\n evaluated\n .effectiveRelativeMagnitudeMultiplier,\n normalizedTimeWeight,\n timeMeasureSeconds\n };\n }\n );\n\n return {\n sourceId: context.source.sourceId,\n sourceEnabled:\n context.source.enabled,\n temporalProfileId:\n input.temporalProfile.profileId,\n bindingId:\n context.binding.bindingId,\n waveformId:\n context.waveform.waveformId,\n timeReference:\n \"first-opening-boundary-phase\",\n localExposureWindow: {\n startSecondsFromCaptureReference:\n window\n .startOffsetSecondsFromOpeningReference,\n endSecondsFromCaptureReference:\n window\n .endOffsetSecondsFromOpeningReference,\n durationSeconds\n },\n quadratureScheme:\n \"uniform-midpoint\",\n temporalSampleCount:\n input.temporalSampleCount,\n nodes,\n averageRelativeMagnitudeMultiplier:\n averageMultiplier,\n integratedRelativeMagnitudeSeconds:\n integratedMultiplierSeconds,\n averageEffectiveRelativeMagnitudeMultiplier:\n averageEffectiveMultiplier,\n integratedEffectiveRelativeMagnitudeSeconds:\n integratedEffectiveMultiplierSeconds,\n sourceMagnitudeApplied: false,\n materialTransportApplied: false,\n sceneRadianceCalculated: false,\n sensorReadoutTimingUsed: false,\n automaticExposureResolved: false,\n convergenceErrorEstimated: false\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"illumination-temporal.js","sourceRoot":"","sources":["../../src/schema/illumination-temporal.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;GASG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EACL,iBAAiB,EAElB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,EACvB,MAAM,uBAAuB,CAAC;AAQ/B,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,6BAA6B,EAAE,mBAAmB,IAAI,aAAa,EAAE,0BAA0B,IAAI,qBAAqB,EAAE,mBAAmB,IAAI,aAAa,EAAE,2BAA2B,IAAI,qBAAqB,EAAE,4BAA4B,IAAI,qBAAqB,EAAE,8BAA8B,IAAI,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACra,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,MAAM,CAAC,MAAM,kDAAkD,GAC7D,OAAgB,CAAC;AA8KnB,SAAS,8BAA8B,CACrC,KAAc,EACd,IAAY;IAEZ,MAAM,QAAQ,GAAG,iBAAiB,CAChC,KAAK,EACL,IAAI,CACL,CAAC;IACF,IACE,CAAC,QAAQ,CAAC,IAAI,CACZ,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,WAAW;QACf,eAAe;QACjB,KAAK,CAAC,WAAW;YACf,gBAAgB,CACrB,EACD,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,IAAI;YACF,2GAA2G,CAC9G,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,4BAA4B,CACnC,KAAc,EACd,IAAY;IAEZ,MAAM,MAAM,GAAG,aAAa,CAC1B,KAAK,EACL,IAAI,EAAE,IAAI,CACX,CAAC;IACF,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,kBAAkB,EAAE,CAAC,MAAM,EAAE,kBAAkB,EAAE,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC1J,IACE,MAAM,CAAC,IAAI;QACX,kBAAkB,EAClB,CAAC;QACD,OAAO;YACL,IAAI,EAAE,kBAAkB;YACxB,gBAAgB,EACd,wBAAwB,CACtB,MAAM,CAAC,gBAAgB,EACvB,IAAI;gBACF,mBAAmB,CACtB;YACH,KAAK,EAAE,qBAAqB,CAC1B,MAAM,CAAC,KAAK,EACZ,IAAI,GAAG,QAAQ,CAChB;SACF,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;QACrC,OAAO;YACL,IAAI,EAAE,gBAAgB;YACtB,UAAU,EACR,qBAAqB,CACnB,MAAM,CAAC,UAAU,EACjB,IAAI,GAAG,aAAa,CACrB;SACJ,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,yBAAyB,CACjC,IAAI,GAAG,mBAAmB,CAC3B,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAC3B,KAAc,EACd,IAAY;IAEZ,IACE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACrB,KAAK,CAAC,MAAM,GAAG,CAAC,EAChB,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,IAAI;YACF,qCAAqC,CACxC,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,GACV,MAAM,CAAC,iBAAiB,CAAC;IAC3B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAChC,MAAM,UAAU,GACd,IAAI,GAAG,GAAG,GAAG,KAAK,GAAG,GAAG,CAAC;QAC3B,MAAM,MAAM,GAAG,aAAa,CAC1B,KAAK,EACL,UAAU,EAAE,CAAC,kCAAkC,EAAE,6BAA6B,CAAC,CAChF,CAAC;QACF,MAAM,IAAI,GACR,wBAAwB,CACtB,MAAM;aACH,gCAAgC,EACnC,UAAU;YACR,mCAAmC,CACtC,CAAC;QACJ,IAAI,IAAI,IAAI,QAAQ,EAAE,CAAC;YACrB,MAAM,IAAI,yBAAyB,CACjC,IAAI;gBACF,qCAAqC,CACxC,CAAC;QACJ,CAAC;QACD,QAAQ,GAAG,IAAI,CAAC;QAChB,OAAO;YACL,gCAAgC,EAC9B,IAAI;YACN,2BAA2B,EACzB,wBAAwB,CACtB,MAAM;iBACH,2BAA2B,EAC9B,UAAU;gBACR,8BAA8B,CACjC;SACJ,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,SAAS,CAAU,CAAC;AAEpJ,SAAS,aAAa,CACpB,KAAc,EACd,IAAY;IAEZ,MAAM,MAAM,GAAG,aAAa,CAC1B,KAAK,EACL,IAAI,EAAE,IAAI,CACX,CAAC;IACF,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE;QACzC,+BAA+B,EAAE,CAAC,GAAG,oBAAoB,EAAE,wBAAwB,CAAC;QACpF,8BAA8B,EAAE,CAAC,GAAG,oBAAoB,EAAE,eAAe,EAAE,4BAA4B,CAAC;KACzG,EAAE,IAAI,CAAC,CAAC;IACT,IAAI,MAAM,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,IAAI,yBAAyB,CACjC,IAAI,GAAG,wBAAwB,CAChC,CAAC;IACJ,CAAC;IACD,IACE,MAAM,CAAC,aAAa;QACpB,kBAAkB,EAClB,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,IAAI;YACF,4CAA4C,CAC/C,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GACd,qBAAqB,CACnB,MAAM,CAAC,UAAU,EACjB,IAAI,GAAG,aAAa,CACrB,CAAC;IACJ,MAAM,gBAAgB,GACpB,qBAAqB,CACnB,MAAM,CAAC,gBAAgB,EACvB,IAAI,GAAG,mBAAmB,CAC3B,CAAC;IACJ,MAAM,WAAW,GACf,gBAAgB,CACd,MAAM,CAAC,WAAW,EAClB,IAAI,GAAG,cAAc,CACtB,CAAC;IACJ,IACE,gBAAgB,KAAK,YAAY;QACjC,WAAW,CAAC,IAAI,KAAK,UAAU,EAC/B,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,IAAI;YACF,qEAAqE,CACxE,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GACZ,8BAA8B,CAC5B,MAAM,CAAC,QAAQ,EACf,IAAI,GAAG,WAAW,CACnB,CAAC;IACJ,MAAM,OAAO,GACX,oBAAoB,CAClB,MAAM,CAAC,OAAO,EACd,IAAI,GAAG,UAAU,CAClB,CAAC;IAEJ,IACE,OAAO,CAAC,CAAC,CAAE;SACR,gCAAgC;QACnC,CAAC,EACD,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,IAAI;YACF,4CAA4C,CAC/C,CAAC;IACJ,CAAC;IAED,IACE,MAAM,CAAC,IAAI;QACX,+BAA+B,EAC/B,CAAC;QACD,IACE,MAAM,CAAC,sBAAsB;YAC7B,MAAM,EACN,CAAC;YACD,MAAM,IAAI,yBAAyB,CACjC,IAAI;gBACF,yCAAyC,CAC5C,CAAC;QACJ,CAAC;QACD,OAAO;YACL,IAAI,EACF,+BAA+B;YACjC,UAAU;YACV,QAAQ,EAAE,GAAG;YACb,gBAAgB;YAChB,WAAW;YACX,QAAQ;YACR,aAAa,EACX,kBAAkB;YACpB,OAAO;YACP,sBAAsB,EACpB,MAAM;SACT,CAAC;IACJ,CAAC;IAED,IACE,MAAM,CAAC,IAAI;QACX,8BAA8B,EAC9B,CAAC;QACD,MAAM,aAAa,GACjB,qBAAqB,CACnB,MAAM,CAAC,aAAa,EACpB,IAAI,GAAG,gBAAgB,CACxB,CAAC;QACJ,MAAM,IAAI,GACR,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;QAC/B,IACE,IAAI;aACD,gCAAgC;YACnC,aAAa,EACb,CAAC;YACD,MAAM,IAAI,yBAAyB,CACjC,IAAI;gBACF,6CAA6C,CAChD,CAAC;QACJ,CAAC;QACD,IACE,OAAO,CAAC,CAAC,CAAE;aACR,2BAA2B;YAC9B,IAAI,CAAC,2BAA2B,EAChC,CAAC;YACD,MAAM,IAAI,yBAAyB,CACjC,IAAI;gBACF,4CAA4C,CAC/C,CAAC;QACJ,CAAC;QACD,IACE,MAAM,CAAC,0BAA0B;YACjC,IAAI,EACJ,CAAC;YACD,MAAM,IAAI,yBAAyB,CACjC,IAAI;gBACF,2CAA2C,CAC9C,CAAC;QACJ,CAAC;QACD,OAAO;YACL,IAAI,EACF,8BAA8B;YAChC,UAAU;YACV,QAAQ,EAAE,GAAG;YACb,gBAAgB;YAChB,WAAW;YACX,QAAQ;YACR,aAAa,EACX,kBAAkB;YACpB,OAAO;YACP,aAAa;YACb,0BAA0B,EACxB,IAAI;SACP,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,yBAAyB,CACjC,IAAI,GAAG,mBAAmB,CAC3B,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CACzB,KAAc,EACd,IAAY;IAEZ,MAAM,MAAM,GAAG,aAAa,CAC1B,KAAK,EACL,IAAI,EAAE,CAAC,sBAAsB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,6CAA6C,EAAE,UAAU,CAAC,CAC1K,CAAC;IACF,IACE,MAAM,CAAC,oBAAoB;QAC3B,8BAA8B,EAC9B,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,IAAI;YACF,+DAA+D,CAClE,CAAC;IACJ,CAAC;IAED,MAAM,gBAAgB,GACpB,qBAAqB,CACnB,MAAM,CAAC,gBAAgB,EACvB,IAAI,GAAG,mBAAmB,CAC3B,CAAC;IACJ,MAAM,iBAAiB,GACrB,4BAA4B,CAC1B,MAAM,CAAC,iBAAiB,EACxB,IAAI,GAAG,oBAAoB,CAC5B,CAAC;IACJ,IACE,gBAAgB,KAAK,YAAY;QACjC,iBAAiB,CAAC,IAAI;YACpB,kBAAkB,EACpB,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,IAAI;YACF,oFAAoF,CACvF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,SAAS,EACP,qBAAqB,CACnB,MAAM,CAAC,SAAS,EAChB,IAAI,GAAG,YAAY,CACpB;QACH,QAAQ,EACN,qBAAqB,CACnB,MAAM,CAAC,QAAQ,EACf,IAAI,GAAG,WAAW,CACnB;QACH,UAAU,EACR,qBAAqB,CACnB,MAAM,CAAC,UAAU,EACjB,IAAI,GAAG,aAAa,CACrB;QACH,oBAAoB,EAClB,8BAA8B;QAChC,2CAA2C,EACzC,aAAa,CACX,MAAM;aACH,2CAA2C,EAC9C,IAAI;YACF,8CAA8C,CACjD;QACH,gBAAgB;QAChB,iBAAiB;QACjB,QAAQ,EAAE,iBAAiB,CACzB,MAAM,CAAC,QAAQ,EACf,IAAI,GAAG,WAAW,CACnB;KACF,CAAC;AACJ,CAAC;AAED,wFAAwF;AACxF,MAAM,6BAA6B,GAAG;IACpC,2CAA2C,EAAE,IAAI,EAAE,uCAAuC,EAAE,KAAK;IACjG,+BAA+B,EAAE,KAAK;CAC9B,CAAC;AAEX;;;;;;GAMG;AACH,MAAM,UAAU,qCAAqC,CACnD,KAAc;IAEd,MAAM,MAAM,GAAG,aAAa,CAC1B,KAAK,EACL,kCAAkC,EAAE,CAAC,eAAe,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,SAAS,EAAE,uBAAuB,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CACjM,CAAC;IACF,6BAA6B,CAAC,MAAM,EAAE,6BAA6B,EAAE,kCAAkC,CAAC,CAAC;IACzG,IACE,MAAM,CAAC,aAAa;QACpB,kDAAkD,EAClD,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,0DAA0D;YACxD,kDAAkD;YAClD,IAAI,CACP,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,yBAAyB,CACjC,8DAA8D,CAC/D,CAAC;IACJ,CAAC;IACD,IACE,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,EACrC,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,mEAAmE,CACpE,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GACb,MAAM,CAAC,SAAS,CAAC,GAAG,CAClB,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CACf,aAAa,CACX,KAAK,EACL,6CAA6C;QAC3C,KAAK;QACL,GAAG,CACN,CACJ,CAAC;IACJ,MAAM,WAAW,GACf,SAAS,CAAC,GAAG,CACX,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAC5B,CAAC;IACJ,IACE,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI;QACzB,WAAW,CAAC,MAAM,EAClB,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,sFAAsF,CACvF,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,GAClB,MAAM,CAAC,cAAc,CAAC,GAAG,CACvB,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CACf,kBAAkB,CAChB,KAAK,EACL,kDAAkD;QAChD,KAAK;QACL,GAAG,CACN,CACJ,CAAC;IACJ,MAAM,UAAU,GACd,cAAc,CAAC,GAAG,CAChB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAC3B,CAAC;IACJ,IACE,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI;QACxB,UAAU,CAAC,MAAM,EACjB,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,0FAA0F,CAC3F,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GACb,cAAc,CAAC,GAAG,CAChB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAC1B,CAAC;IACJ,IACE,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI;QACvB,SAAS,CAAC,MAAM,EAChB,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,sGAAsG,CACvG,CAAC;IACJ,CAAC;IACD,MAAM,aAAa,GACjB,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;IACvB,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;QACrC,IACE,CAAC,aAAa,CAAC,GAAG,CAChB,OAAO,CAAC,UAAU,CACnB,EACD,CAAC;YACD,MAAM,IAAI,yBAAyB,CACjC,mFAAmF,CACpF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,aAAa,EACX,kDAAkD;QACpD,SAAS,EACP,qBAAqB,CACnB,MAAM,CAAC,SAAS,EAChB,4CAA4C,CAC7C;QACH,OAAO,EACL,qBAAqB,CACnB,MAAM,CAAC,OAAO,EACd,0CAA0C,CAC3C;QACH,qBAAqB,EACnB,qBAAqB,CACnB,MAAM,CAAC,qBAAqB,EAC5B,wDAAwD,CACzD;QACH,QAAQ,EAAE,iBAAiB,CACzB,MAAM,CAAC,QAAQ,EACf,2CAA2C,CAC5C;QACD,SAAS;QACT,cAAc;QACd,2CAA2C,EACzC,IAAI;QACN,uCAAuC,EACrC,KAAK;QACP,+BAA+B,EAC7B,KAAK;KACR,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAC7B,mBAC0B,EAC1B,eACkC;IAElC,IACE,eAAe,CAAC,OAAO;QACvB,mBAAmB,CAAC,OAAO,EAC3B,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,4EAA4E,CAC7E,CAAC;IACJ,CAAC;IACD,IACE,eAAe;SACZ,qBAAqB;QACxB,mBAAmB,CAAC,SAAS,EAC7B,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,mGAAmG,CACpG,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,GAClB,IAAI,GAAG,CACL,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAC7B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAC1B,CACF,CAAC;IACJ,KACE,MAAM,OAAO,IACb,eAAe,CAAC,cAAc,EAC9B,CAAC;QACD,IACE,CAAC,cAAc,CAAC,GAAG,CACjB,OAAO,CAAC,QAAQ,CACjB,EACD,CAAC;YACD,MAAM,IAAI,2BAA2B,CACnC,8GAA8G,CAC/G,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,+BAA+B,CACtC,mBAC0B,EAC1B,eACkC,EAClC,QAAgB;IAShB,sBAAsB,CACpB,mBAAmB,EACnB,eAAe,CAChB,CAAC;IAEF,MAAM,MAAM,GACV,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAC9B,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAC9B,CAAC;IACJ,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,2BAA2B,CACnC,gEAAgE,CACjE,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GACX,eAAe,CAAC,cAAc,CAAC,IAAI,CACjC,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAC9B,CAAC;IACJ,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,2BAA2B,CACnC,8FAA8F,CAC/F,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GACZ,eAAe,CAAC,SAAS,CAAC,IAAI,CAC5B,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,UAAU;QAChB,OAAO,CAAC,UAAU,CACrB,CAAC;IACJ,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,IAAI,2BAA2B,CACnC,6EAA6E,CAC9E,CAAC;IACJ,CAAC;IAED,OAAO;QACL,MAAM;QACN,OAAO;QACP,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAC1B,OACoD,EACpD,WAAmB;IAEnB,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC;IAC1B,MAAM,IAAI,GACR,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;IAE/B,IACE,WAAW;QACX,KAAK,CAAC,gCAAgC,EACtC,CAAC;QACD,OAAO,KAAK;aACT,2BAA2B,CAAC;IACjC,CAAC;IACD,IACE,WAAW;QACX,IAAI,CAAC,gCAAgC,EACrC,CAAC;QACD,OAAO,IAAI;aACR,2BAA2B,CAAC;IACjC,CAAC;IAED,KACE,IAAI,KAAK,GAAG,CAAC,EACb,KAAK,GAAG,OAAO,CAAC,MAAM,EACtB,KAAK,IAAI,CAAC,EACV,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAE,CAAC;QAC9B,IACE,WAAW;YACX,KAAK;iBACF,gCAAgC,EACnC,CAAC;YACD,MAAM,IAAI,GACR,OAAO,CAAC,KAAK,GAAG,CAAC,CAAE,CAAC;YACtB,MAAM,IAAI,GACR,KAAK;iBACF,gCAAgC;gBACnC,IAAI;qBACD,gCAAgC,CAAC;YACtC,MAAM,KAAK,GACT,CAAC,WAAW;gBACV,IAAI;qBACD,gCAAgC,CAAC;gBACtC,IAAI,CAAC;YACP,OAAO,CACL,IAAI;iBACD,2BAA2B;gBAC9B,KAAK;oBACH,CAAC,KAAK;yBACH,2BAA2B;wBAC5B,IAAI;6BACD,2BAA2B,CAAC,CACpC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,IAAI;SACR,2BAA2B,CAAC;AACjC,CAAC;AAED,SAAS,gBAAgB,CACvB,QACmC,EACnC,mBAA2B;IAE3B,IACE,QAAQ,CAAC,IAAI;QACb,+BAA+B,EAC/B,CAAC;QACD,MAAM,IAAI,GACR,QAAQ,CAAC,OAAO,CACd,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAC3B,CAAC;QACL,IACE,mBAAmB,GAAG,CAAC;YACvB,mBAAmB;gBACjB,IAAI;qBACD,gCAAgC,EACrC,CAAC;YACD,OAAO,CAAC,CAAC;QACX,CAAC;QACD,OAAO,mBAAmB,CACxB,QAAQ,CAAC,OAAO,EAChB,mBAAmB,CACpB,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAChB,cAAc,CACZ,mBAAmB,EACnB,QAAQ,CAAC,aAAa,CACvB,CAAC;IACJ,OAAO,mBAAmB,CACxB,QAAQ,CAAC,OAAO,EAChB,YAAY,CACb,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,2CAA2C,CACzD,KACkD;IAElD,gBAAgB,CAAC,KAAK,EAAE,6CAA6C,EAAE,CAAC,qBAAqB,EAAE,iBAAiB,EAAE,UAAU,EAAE,iCAAiC,CAAC,CAAC,CAAC;IAClK,IACE,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ;QAClC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAClC,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,sCAAsC,CACvC,CAAC;IACJ,CAAC;IACD,IACE,OAAO,KAAK;SACT,+BAA+B;QAChC,QAAQ;QACV,CAAC,MAAM,CAAC,QAAQ,CACd,KAAK;aACF,+BAA+B,CACnC,EACD,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,iDAAiD,CAClD,CAAC;IACJ,CAAC;IAED,MAAM,EACJ,MAAM,EACN,OAAO,EACP,QAAQ,EACT,GACC,+BAA+B,CAC7B,KAAK,CAAC,mBAAmB,EACzB,KAAK,CAAC,eAAe,EACrB,KAAK,CAAC,QAAQ,CACf,CAAC;IAEJ,MAAM,mBAAmB,GACvB,KAAK;SACF,+BAA+B;QAClC,OAAO;aACJ,2CAA2C,CAAC;IACjD,MAAM,UAAU,GACd,gBAAgB,CACd,QAAQ,EACR,mBAAmB,CACpB,CAAC;IAEJ,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,aAAa,EAAE,MAAM,CAAC,OAAO;QAC7B,iBAAiB,EACf,KAAK,CAAC,eAAe,CAAC,SAAS;QACjC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,UAAU,EAAE,QAAQ,CAAC,UAAU;QAC/B,oBAAoB,EAClB,8BAA8B;QAChC,+BAA+B,EAC7B,KAAK;aACF,+BAA+B;QACpC,wCAAwC,EACtC,mBAAmB;QACrB,YAAY,EAAE,QAAQ,CAAC,IAAI;QAC3B,2BAA2B,EACzB,UAAU;QACZ,oCAAoC,EAClC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACjC,sBAAsB,EAAE,KAAK;QAC7B,wBAAwB,EAAE,KAAK;QAC/B,uBAAuB,EAAE,KAAK;QAC9B,uBAAuB,EAAE,KAAK;QAC9B,yBAAyB,EAAE,KAAK;KACjC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,8DAA8D,CAC5E,KACmD;IAEnD,gBAAgB,CAAC,KAAK,EAAE,gEAAgE,EAAE,CAAC,qBAAqB,EAAE,iBAAiB,EAAE,UAAU,EAAE,iBAAiB,EAAE,aAAa,EAAE,qBAAqB,CAAC,CAAC,CAAC;IAC3M,sBAAsB,CACpB,qBAAqB,EACrB,KAAK,CAAC,mBAAmB,CAC1B,CAAC;IACF,IACE,CAAC,MAAM,CAAC,aAAa,CACnB,KAAK,CAAC,WAAW,CAClB;QACD,KAAK,CAAC,WAAW,GAAG,CAAC,EACrB,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,kDAAkD,CACnD,CAAC;IACJ,CAAC;IACD,IACE,KAAK,CAAC,eAAe;SAClB,aAAa;QAChB,8BAA8B,EAC9B,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,4EAA4E,CAC7E,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GACV,KAAK,CAAC,eAAe,CAAC,OAAO,CAC3B,KAAK,CAAC,WAAW,CAClB,CAAC;IACJ,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,2BAA2B,CACnC,iDAAiD,CAClD,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GACX,+BAA+B,CAC7B,KAAK,CAAC,mBAAmB,EACzB,KAAK,CAAC,eAAe,EACrB,KAAK,CAAC,QAAQ,CACf,CAAC;IACJ,MAAM,eAAe,GACnB,MAAM,CAAC,4BAA4B,CAAC;IACtC,MAAM,oBAAoB,GACxB,CAAC,GAAG,KAAK,CAAC,mBAAmB,CAAC;IAChC,MAAM,kBAAkB,GACtB,eAAe;QACf,KAAK,CAAC,mBAAmB,CAAC;IAE5B,IAAI,iBAAiB,GAAG,CAAC,CAAC;IAC1B,IAAI,2BAA2B,GAC7B,CAAC,CAAC;IACJ,IAAI,0BAA0B,GAC5B,CAAC,CAAC;IACJ,IAAI,oCAAoC,GACtC,CAAC,CAAC;IAEJ,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CACtB;QACE,MAAM,EACJ,KAAK,CAAC,mBAAmB;KAC5B,EACD,CAAC,CAAC,EAAE,mBAAmB,EAAE,EAAE;QACzB,MAAM,kBAAkB,GACtB,CAAC,mBAAmB,GAAG,GAAG,CAAC;YAC3B,KAAK,CAAC,mBAAmB,CAAC;QAC5B,MAAM,kBAAkB,GACtB,MAAM;aACH,sCAAsC;YACzC,kBAAkB;gBAChB,eAAe,CAAC;QACpB,MAAM,SAAS,GACb,2CAA2C,CACzC;YACE,mBAAmB,EACjB,KAAK,CAAC,mBAAmB;YAC3B,eAAe,EACb,KAAK,CAAC,eAAe;YACvB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,+BAA+B,EAC7B,kBAAkB;SACrB,CACF,CAAC;QAEJ,iBAAiB;YACf,SAAS;iBACN,2BAA2B;gBAC9B,oBAAoB,CAAC;QACvB,2BAA2B;YACzB,SAAS;iBACN,2BAA2B;gBAC9B,kBAAkB,CAAC;QACrB,0BAA0B;YACxB,SAAS;iBACN,oCAAoC;gBACvC,oBAAoB,CAAC;QACvB,oCAAoC;YAClC,SAAS;iBACN,oCAAoC;gBACvC,kBAAkB,CAAC;QAErB,OAAO;YACL,mBAAmB;YACnB,kBAAkB;YAClB,+BAA+B,EAC7B,kBAAkB;YACpB,wCAAwC,EACtC,SAAS;iBACN,wCAAwC;YAC7C,2BAA2B,EACzB,SAAS;iBACN,2BAA2B;YAChC,oCAAoC,EAClC,SAAS;iBACN,oCAAoC;YACzC,oBAAoB;YACpB,kBAAkB;SACnB,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,OAAO;QACL,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ;QACjC,aAAa,EACX,OAAO,CAAC,MAAM,CAAC,OAAO;QACxB,iBAAiB,EACf,KAAK,CAAC,eAAe,CAAC,SAAS;QACjC,SAAS,EACP,OAAO,CAAC,OAAO,CAAC,SAAS;QAC3B,UAAU,EACR,OAAO,CAAC,QAAQ,CAAC,UAAU;QAC7B,aAAa,EACX,8BAA8B;QAChC,mBAAmB,EAAE;YACnB,gCAAgC,EAC9B,MAAM;iBACH,sCAAsC;YAC3C,8BAA8B,EAC5B,MAAM;iBACH,oCAAoC;YACzC,eAAe;SAChB;QACD,gBAAgB,EACd,kBAAkB;QACpB,mBAAmB,EACjB,KAAK,CAAC,mBAAmB;QAC3B,KAAK;QACL,kCAAkC,EAChC,iBAAiB;QACnB,kCAAkC,EAChC,2BAA2B;QAC7B,2CAA2C,EACzC,0BAA0B;QAC5B,2CAA2C,EACzC,oCAAoC;QACtC,sBAAsB,EAAE,KAAK;QAC7B,wBAAwB,EAAE,KAAK;QAC/B,uBAAuB,EAAE,KAAK;QAC9B,uBAAuB,EAAE,KAAK;QAC9B,yBAAyB,EAAE,KAAK;QAChC,yBAAyB,EAAE,KAAK;KACjC,CAAC;AACJ,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Time-varying light sources, such as flicker or a pulsed light.\n *\n * A temporal profile sits on top of an existing illumination profile. Each binding multiplies\n * one source by a relative waveform over time. The base source magnitude and spectrum still\n * apply, and sources with no binding stay constant. This module parses the profile, evaluates\n * a waveform at one capture time, and integrates it over an exposure window.\n * @see docs/SCENE_RADIANCE_AND_ILLUMINATION.md for equations, coordinate/unit conventions, blockers\n * and support limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport {\n InvalidScientificInputError,\n requirePositiveInteger\n} from \"../core/validation.js\";\nimport type {\n CaptureExposureWindows\n} from \"../sensor/exposure-window.js\";\nimport type {\n SceneIlluminationProfile,\n SceneIlluminationUncertainty\n} from \"./illumination.js\";\nimport { requireInputKeys, rejectUnknownVariantFields, requireFixedFieldsWhenPresent, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, requireConfigFinite as requireFinite, parseConfigScientificStatus as parseScientificStatus, requireConfigFiniteAboveZero as requirePositiveFinite, requireConfigFiniteAtLeastZero as requireNonNegativeFinite } from \"../core/record-validation.js\";\nimport { parseUncertainty } from \"../optics/lens-psf-profile.js\";\nimport { positiveModulo } from \"../optics/complex-pupil-psf.js\";\n\nexport const SCENE_ILLUMINATION_TEMPORAL_PROFILE_SCHEMA_VERSION =\n \"0.1.0\" as const;\n\nexport type SceneIlluminationTemporalScientificStatus =\n | \"calibrated\"\n | \"approximation\";\n\nexport interface SceneIlluminationTemporalWaveformSample {\n timeSecondsFromWaveformReference: number;\n relativeMagnitudeMultiplier: number;\n}\n\ninterface SceneIlluminationTemporalWaveformBase {\n waveformId: string;\n timeUnit: \"s\";\n scientificStatus:\n SceneIlluminationTemporalScientificStatus;\n uncertainty: SceneIlluminationUncertainty;\n evidence: readonly EvidenceProvenance[];\n interpolation: \"piecewise-linear\";\n samples:\n readonly SceneIlluminationTemporalWaveformSample[];\n}\n\nexport type SceneIlluminationTemporalWaveform =\n | (SceneIlluminationTemporalWaveformBase & {\n kind:\n \"aperiodic-relative-multiplier\";\n outsideSupportBehavior: \"zero\";\n })\n | (SceneIlluminationTemporalWaveformBase & {\n kind:\n \"periodic-relative-multiplier\";\n periodSeconds: number;\n endpointContinuityRequired: true;\n });\n\nexport type SceneIlluminationTemporalRegistrationUncertainty =\n | {\n kind: \"absolute-seconds\";\n plusMinusSeconds: number;\n basis: string;\n }\n | {\n kind: \"not-quantified\";\n limitation: string;\n };\n\nexport interface SceneIlluminationTemporalSourceBinding {\n bindingId: string;\n sourceId: string;\n waveformId: string;\n captureTimeReference:\n \"first-opening-boundary-phase\";\n /**\n * The capture time at which the waveform's own t=0 falls.\n *\n * waveformTime = captureTime - waveformTimeZeroSecondsFromCaptureReference\n */\n waveformTimeZeroSecondsFromCaptureReference:\n number;\n scientificStatus:\n SceneIlluminationTemporalScientificStatus;\n timingUncertainty:\n SceneIlluminationTemporalRegistrationUncertainty;\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface SceneIlluminationTemporalProfile {\n schemaVersion:\n typeof SCENE_ILLUMINATION_TEMPORAL_PROFILE_SCHEMA_VERSION;\n profileId: string;\n sceneId: string;\n illuminationProfileId: string;\n evidence: readonly EvidenceProvenance[];\n waveforms:\n readonly SceneIlluminationTemporalWaveform[];\n sourceBindings:\n readonly SceneIlluminationTemporalSourceBinding[];\n baseIlluminationProfileRemainsAuthoritative:\n true;\n sensorReadoutTimingUsedAsExposureTiming:\n false;\n automaticExposurePolicyIncluded: false;\n}\n\nexport interface EvaluateSceneIlluminationTemporalMultiplierInput {\n illuminationProfile:\n SceneIlluminationProfile;\n temporalProfile:\n SceneIlluminationTemporalProfile;\n sourceId: string;\n captureTimeSecondsFromReference: number;\n}\n\nexport interface SceneIlluminationTemporalMultiplierEvaluation {\n sourceId: string;\n sourceEnabled: boolean;\n temporalProfileId: string;\n bindingId: string;\n waveformId: string;\n captureTimeReference:\n \"first-opening-boundary-phase\";\n captureTimeSecondsFromReference: number;\n waveformTimeSecondsFromWaveformReference:\n number;\n waveformKind:\n SceneIlluminationTemporalWaveform[\"kind\"];\n relativeMagnitudeMultiplier: number;\n effectiveRelativeMagnitudeMultiplier:\n number;\n sourceMagnitudeApplied: false;\n materialTransportApplied: false;\n sceneRadianceCalculated: false;\n sensorReadoutTimingUsed: false;\n automaticExposureResolved: false;\n}\n\nexport interface IntegrateSceneIlluminationTemporalMultiplierInput {\n illuminationProfile:\n SceneIlluminationProfile;\n temporalProfile:\n SceneIlluminationTemporalProfile;\n sourceId: string;\n exposureWindows: CaptureExposureWindows;\n sampleIndex: number;\n temporalSampleCount: number;\n}\n\nexport interface SceneIlluminationTemporalIntegrationNode {\n temporalSampleIndex: number;\n localExposurePhase: number;\n captureTimeSecondsFromReference: number;\n waveformTimeSecondsFromWaveformReference:\n number;\n relativeMagnitudeMultiplier: number;\n effectiveRelativeMagnitudeMultiplier:\n number;\n normalizedTimeWeight: number;\n timeMeasureSeconds: number;\n}\n\nexport interface SceneIlluminationTemporalExposureIntegration {\n sourceId: string;\n sourceEnabled: boolean;\n temporalProfileId: string;\n bindingId: string;\n waveformId: string;\n timeReference:\n \"first-opening-boundary-phase\";\n localExposureWindow: {\n startSecondsFromCaptureReference: number;\n endSecondsFromCaptureReference: number;\n durationSeconds: number;\n };\n quadratureScheme: \"uniform-midpoint\";\n temporalSampleCount: number;\n nodes:\n readonly SceneIlluminationTemporalIntegrationNode[];\n averageRelativeMagnitudeMultiplier:\n number;\n integratedRelativeMagnitudeSeconds:\n number;\n averageEffectiveRelativeMagnitudeMultiplier:\n number;\n integratedEffectiveRelativeMagnitudeSeconds:\n number;\n sourceMagnitudeApplied: false;\n materialTransportApplied: false;\n sceneRadianceCalculated: false;\n sensorReadoutTimingUsed: false;\n automaticExposureResolved: false;\n convergenceErrorEstimated: false;\n}\n\nfunction requireReusableNumericEvidence(\n value: unknown,\n path: string\n): readonly EvidenceProvenance[] {\n const evidence = parseEvidenceList(\n value,\n path\n );\n if (\n !evidence.some(\n (entry) =>\n entry.reuseStatus ===\n \"reusable-data\" ||\n entry.reuseStatus ===\n \"photivra-owned\"\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must contain reusable-data or photivra-owned evidence because the waveform embeds reusable numeric data.\"\n );\n }\n return evidence;\n}\n\nfunction parseRegistrationUncertainty(\n value: unknown,\n path: string\n): SceneIlluminationTemporalRegistrationUncertainty {\n const record = requireRecord(\n value,\n path, null\n );\n rejectUnknownVariantFields(record, \"kind\", { \"absolute-seconds\": [\"kind\", \"plusMinusSeconds\", \"basis\"], \"not-quantified\": [\"kind\", \"limitation\"] }, path);\n if (\n record.kind ===\n \"absolute-seconds\"\n ) {\n return {\n kind: \"absolute-seconds\",\n plusMinusSeconds:\n requireNonNegativeFinite(\n record.plusMinusSeconds,\n path +\n \".plusMinusSeconds\"\n ),\n basis: requireNonEmptyString(\n record.basis,\n path + \".basis\"\n )\n };\n }\n if (record.kind === \"not-quantified\") {\n return {\n kind: \"not-quantified\",\n limitation:\n requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseWaveformSamples(\n value: unknown,\n path: string\n): readonly SceneIlluminationTemporalWaveformSample[] {\n if (\n !Array.isArray(value) ||\n value.length < 2\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must contain at least two samples.\"\n );\n }\n\n let previous =\n Number.NEGATIVE_INFINITY;\n return value.map((entry, index) => {\n const samplePath =\n path + \"[\" + index + \"]\";\n const sample = requireRecord(\n entry,\n samplePath, [\"timeSecondsFromWaveformReference\", \"relativeMagnitudeMultiplier\"]\n );\n const time =\n requireNonNegativeFinite(\n sample\n .timeSecondsFromWaveformReference,\n samplePath +\n \".timeSecondsFromWaveformReference\"\n );\n if (time <= previous) {\n throw new InvalidConfigurationError(\n path +\n \" times must be strictly increasing.\"\n );\n }\n previous = time;\n return {\n timeSecondsFromWaveformReference:\n time,\n relativeMagnitudeMultiplier:\n requireNonNegativeFinite(\n sample\n .relativeMagnitudeMultiplier,\n samplePath +\n \".relativeMagnitudeMultiplier\"\n )\n };\n });\n}\n\nconst WAVEFORM_BASE_FIELDS = [\"kind\", \"waveformId\", \"timeUnit\", \"scientificStatus\", \"uncertainty\", \"evidence\", \"interpolation\", \"samples\"] as const;\n\nfunction parseWaveform(\n value: unknown,\n path: string\n): SceneIlluminationTemporalWaveform {\n const record = requireRecord(\n value,\n path, null\n );\n rejectUnknownVariantFields(record, \"kind\", {\n \"aperiodic-relative-multiplier\": [...WAVEFORM_BASE_FIELDS, \"outsideSupportBehavior\"],\n \"periodic-relative-multiplier\": [...WAVEFORM_BASE_FIELDS, \"periodSeconds\", \"endpointContinuityRequired\"]\n }, path);\n if (record.timeUnit !== \"s\") {\n throw new InvalidConfigurationError(\n path + '.timeUnit must be \"s\".'\n );\n }\n if (\n record.interpolation !==\n \"piecewise-linear\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.interpolation must be \"piecewise-linear\".'\n );\n }\n\n const waveformId =\n requireNonEmptyString(\n record.waveformId,\n path + \".waveformId\"\n );\n const scientificStatus =\n parseScientificStatus(\n record.scientificStatus,\n path + \".scientificStatus\"\n );\n const uncertainty =\n parseUncertainty(\n record.uncertainty,\n path + \".uncertainty\"\n );\n if (\n scientificStatus === \"calibrated\" &&\n uncertainty.kind !== \"relative\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \" calibrated waveform data requires quantified relative uncertainty.\"\n );\n }\n const evidence =\n requireReusableNumericEvidence(\n record.evidence,\n path + \".evidence\"\n );\n const samples =\n parseWaveformSamples(\n record.samples,\n path + \".samples\"\n );\n\n if (\n samples[0]!\n .timeSecondsFromWaveformReference !==\n 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \".samples must begin at waveform-local t=0.\"\n );\n }\n\n if (\n record.kind ===\n \"aperiodic-relative-multiplier\"\n ) {\n if (\n record.outsideSupportBehavior !==\n \"zero\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.outsideSupportBehavior must be \"zero\".'\n );\n }\n return {\n kind:\n \"aperiodic-relative-multiplier\",\n waveformId,\n timeUnit: \"s\",\n scientificStatus,\n uncertainty,\n evidence,\n interpolation:\n \"piecewise-linear\",\n samples,\n outsideSupportBehavior:\n \"zero\"\n };\n }\n\n if (\n record.kind ===\n \"periodic-relative-multiplier\"\n ) {\n const periodSeconds =\n requirePositiveFinite(\n record.periodSeconds,\n path + \".periodSeconds\"\n );\n const last =\n samples[samples.length - 1]!;\n if (\n last\n .timeSecondsFromWaveformReference !==\n periodSeconds\n ) {\n throw new InvalidConfigurationError(\n path +\n \".samples must end exactly at periodSeconds.\"\n );\n }\n if (\n samples[0]!\n .relativeMagnitudeMultiplier !==\n last.relativeMagnitudeMultiplier\n ) {\n throw new InvalidConfigurationError(\n path +\n \" periodic endpoint multipliers must match.\"\n );\n }\n if (\n record.endpointContinuityRequired !==\n true\n ) {\n throw new InvalidConfigurationError(\n path +\n \".endpointContinuityRequired must be true.\"\n );\n }\n return {\n kind:\n \"periodic-relative-multiplier\",\n waveformId,\n timeUnit: \"s\",\n scientificStatus,\n uncertainty,\n evidence,\n interpolation:\n \"piecewise-linear\",\n samples,\n periodSeconds,\n endpointContinuityRequired:\n true\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseSourceBinding(\n value: unknown,\n path: string\n): SceneIlluminationTemporalSourceBinding {\n const record = requireRecord(\n value,\n path, [\"captureTimeReference\", \"scientificStatus\", \"timingUncertainty\", \"bindingId\", \"sourceId\", \"waveformId\", \"waveformTimeZeroSecondsFromCaptureReference\", \"evidence\"]\n );\n if (\n record.captureTimeReference !==\n \"first-opening-boundary-phase\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.captureTimeReference must be \"first-opening-boundary-phase\".'\n );\n }\n\n const scientificStatus =\n parseScientificStatus(\n record.scientificStatus,\n path + \".scientificStatus\"\n );\n const timingUncertainty =\n parseRegistrationUncertainty(\n record.timingUncertainty,\n path + \".timingUncertainty\"\n );\n if (\n scientificStatus === \"calibrated\" &&\n timingUncertainty.kind !==\n \"absolute-seconds\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \" calibrated waveform registration requires quantified absolute timing uncertainty.\"\n );\n }\n\n return {\n bindingId:\n requireNonEmptyString(\n record.bindingId,\n path + \".bindingId\"\n ),\n sourceId:\n requireNonEmptyString(\n record.sourceId,\n path + \".sourceId\"\n ),\n waveformId:\n requireNonEmptyString(\n record.waveformId,\n path + \".waveformId\"\n ),\n captureTimeReference:\n \"first-opening-boundary-phase\",\n waveformTimeZeroSecondsFromCaptureReference:\n requireFinite(\n record\n .waveformTimeZeroSecondsFromCaptureReference,\n path +\n \".waveformTimeZeroSecondsFromCaptureReference\"\n ),\n scientificStatus,\n timingUncertainty,\n evidence: parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\n/** Fixed flags the parser writes; a parsed profile may carry them back in unchanged. */\nconst TEMPORAL_PROFILE_FIXED_FIELDS = {\n baseIlluminationProfileRemainsAuthoritative: true, sensorReadoutTimingUsedAsExposureTiming: false,\n automaticExposurePolicyIncluded: false\n} as const;\n\n/**\n * Parses a time-varying illumination profile that sits on top of one existing\n * illumination profile.\n *\n * The base source magnitude and spectrum still apply. Each binding multiplies one\n * source by one relative waveform over time. Sources with no binding stay constant.\n */\nexport function parseSceneIlluminationTemporalProfile(\n value: unknown\n): SceneIlluminationTemporalProfile {\n const record = requireRecord(\n value,\n \"sceneIlluminationTemporalProfile\", [\"schemaVersion\", \"waveforms\", \"sourceBindings\", \"profileId\", \"sceneId\", \"illuminationProfileId\", \"evidence\", ...Object.keys(TEMPORAL_PROFILE_FIXED_FIELDS)]\n );\n requireFixedFieldsWhenPresent(record, TEMPORAL_PROFILE_FIXED_FIELDS, \"sceneIlluminationTemporalProfile\");\n if (\n record.schemaVersion !==\n SCENE_ILLUMINATION_TEMPORAL_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'sceneIlluminationTemporalProfile.schemaVersion must be \"' +\n SCENE_ILLUMINATION_TEMPORAL_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n if (!Array.isArray(record.waveforms)) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationTemporalProfile.waveforms must be an array.\"\n );\n }\n if (\n !Array.isArray(record.sourceBindings)\n ) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationTemporalProfile.sourceBindings must be an array.\"\n );\n }\n\n const waveforms =\n record.waveforms.map(\n (entry, index) =>\n parseWaveform(\n entry,\n \"sceneIlluminationTemporalProfile.waveforms[\" +\n index +\n \"]\"\n )\n );\n const waveformIds =\n waveforms.map(\n (entry) => entry.waveformId\n );\n if (\n new Set(waveformIds).size !==\n waveformIds.length\n ) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationTemporalProfile.waveforms[].waveformId must not contain duplicates.\"\n );\n }\n\n const sourceBindings =\n record.sourceBindings.map(\n (entry, index) =>\n parseSourceBinding(\n entry,\n \"sceneIlluminationTemporalProfile.sourceBindings[\" +\n index +\n \"]\"\n )\n );\n const bindingIds =\n sourceBindings.map(\n (entry) => entry.bindingId\n );\n if (\n new Set(bindingIds).size !==\n bindingIds.length\n ) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationTemporalProfile.sourceBindings[].bindingId must not contain duplicates.\"\n );\n }\n const sourceIds =\n sourceBindings.map(\n (entry) => entry.sourceId\n );\n if (\n new Set(sourceIds).size !==\n sourceIds.length\n ) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationTemporalProfile supports at most one temporal binding per sourceId in schema 0.1.0.\"\n );\n }\n const waveformIdSet =\n new Set(waveformIds);\n for (const binding of sourceBindings) {\n if (\n !waveformIdSet.has(\n binding.waveformId\n )\n ) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationTemporalProfile source binding references an unknown waveformId.\"\n );\n }\n }\n\n return {\n schemaVersion:\n SCENE_ILLUMINATION_TEMPORAL_PROFILE_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"sceneIlluminationTemporalProfile.profileId\"\n ),\n sceneId:\n requireNonEmptyString(\n record.sceneId,\n \"sceneIlluminationTemporalProfile.sceneId\"\n ),\n illuminationProfileId:\n requireNonEmptyString(\n record.illuminationProfileId,\n \"sceneIlluminationTemporalProfile.illuminationProfileId\"\n ),\n evidence: parseEvidenceList(\n record.evidence,\n \"sceneIlluminationTemporalProfile.evidence\"\n ),\n waveforms,\n sourceBindings,\n baseIlluminationProfileRemainsAuthoritative:\n true,\n sensorReadoutTimingUsedAsExposureTiming:\n false,\n automaticExposurePolicyIncluded:\n false\n };\n}\n\nfunction requireProfileBindings(\n illuminationProfile:\n SceneIlluminationProfile,\n temporalProfile:\n SceneIlluminationTemporalProfile\n): void {\n if (\n temporalProfile.sceneId !==\n illuminationProfile.sceneId\n ) {\n throw new InvalidScientificInputError(\n \"Temporal illumination profile sceneId must match the illumination profile.\"\n );\n }\n if (\n temporalProfile\n .illuminationProfileId !==\n illuminationProfile.profileId\n ) {\n throw new InvalidScientificInputError(\n \"Temporal illumination profile illuminationProfileId must match the supplied illumination profile.\"\n );\n }\n\n const knownSourceIds =\n new Set(\n illuminationProfile.sources.map(\n (entry) => entry.sourceId\n )\n );\n for (\n const binding of\n temporalProfile.sourceBindings\n ) {\n if (\n !knownSourceIds.has(\n binding.sourceId\n )\n ) {\n throw new InvalidScientificInputError(\n \"Temporal illumination source binding references a sourceId that is not declared by the illumination profile.\"\n );\n }\n }\n}\n\nfunction resolveSourceAndTemporalBinding(\n illuminationProfile:\n SceneIlluminationProfile,\n temporalProfile:\n SceneIlluminationTemporalProfile,\n sourceId: string\n): {\n source:\n SceneIlluminationProfile[\"sources\"][number];\n binding:\n SceneIlluminationTemporalSourceBinding;\n waveform:\n SceneIlluminationTemporalWaveform;\n} {\n requireProfileBindings(\n illuminationProfile,\n temporalProfile\n );\n\n const source =\n illuminationProfile.sources.find(\n (entry) =>\n entry.sourceId === sourceId\n );\n if (source === undefined) {\n throw new InvalidScientificInputError(\n \"sourceId is not declared by the supplied illumination profile.\"\n );\n }\n\n const binding =\n temporalProfile.sourceBindings.find(\n (entry) =>\n entry.sourceId === sourceId\n );\n if (binding === undefined) {\n throw new InvalidScientificInputError(\n \"Time-varying source evaluation requires an explicit source waveform-to-capture registration.\"\n );\n }\n\n const waveform =\n temporalProfile.waveforms.find(\n (entry) =>\n entry.waveformId ===\n binding.waveformId\n );\n if (waveform === undefined) {\n throw new InvalidScientificInputError(\n \"Temporal source binding waveformId is not declared by the temporal profile.\"\n );\n }\n\n return {\n source,\n binding,\n waveform\n };\n}\n\nfunction interpolateWaveform(\n samples:\n readonly SceneIlluminationTemporalWaveformSample[],\n timeSeconds: number\n): number {\n const first = samples[0]!;\n const last =\n samples[samples.length - 1]!;\n\n if (\n timeSeconds ===\n first.timeSecondsFromWaveformReference\n ) {\n return first\n .relativeMagnitudeMultiplier;\n }\n if (\n timeSeconds ===\n last.timeSecondsFromWaveformReference\n ) {\n return last\n .relativeMagnitudeMultiplier;\n }\n\n for (\n let index = 1;\n index < samples.length;\n index += 1\n ) {\n const right = samples[index]!;\n if (\n timeSeconds <\n right\n .timeSecondsFromWaveformReference\n ) {\n const left =\n samples[index - 1]!;\n const span =\n right\n .timeSecondsFromWaveformReference -\n left\n .timeSecondsFromWaveformReference;\n const phase =\n (timeSeconds -\n left\n .timeSecondsFromWaveformReference) /\n span;\n return (\n left\n .relativeMagnitudeMultiplier +\n phase *\n (right\n .relativeMagnitudeMultiplier -\n left\n .relativeMagnitudeMultiplier)\n );\n }\n }\n\n return last\n .relativeMagnitudeMultiplier;\n}\n\nfunction evaluateWaveform(\n waveform:\n SceneIlluminationTemporalWaveform,\n waveformTimeSeconds: number\n): number {\n if (\n waveform.kind ===\n \"aperiodic-relative-multiplier\"\n ) {\n const last =\n waveform.samples[\n waveform.samples.length - 1\n ]!;\n if (\n waveformTimeSeconds < 0 ||\n waveformTimeSeconds >\n last\n .timeSecondsFromWaveformReference\n ) {\n return 0;\n }\n return interpolateWaveform(\n waveform.samples,\n waveformTimeSeconds\n );\n }\n\n const periodicTime =\n positiveModulo(\n waveformTimeSeconds,\n waveform.periodSeconds\n );\n return interpolateWaveform(\n waveform.samples,\n periodicTime\n );\n}\n\n/**\n * Returns one registered source's time-varying multiplier at one capture time.\n *\n * Capture time is in seconds from the first opening boundary of the exposure. Sensor\n * readout timing is never used in place of capture time.\n */\nexport function evaluateSceneIlluminationTemporalMultiplier(\n input:\n EvaluateSceneIlluminationTemporalMultiplierInput\n): SceneIlluminationTemporalMultiplierEvaluation {\n requireInputKeys(input, \"evaluateSceneIlluminationTemporalMultiplier\", [\"illuminationProfile\", \"temporalProfile\", \"sourceId\", \"captureTimeSecondsFromReference\"]);\n if (\n typeof input.sourceId !== \"string\" ||\n input.sourceId.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n \"sourceId must be a non-empty string.\"\n );\n }\n if (\n typeof input\n .captureTimeSecondsFromReference !==\n \"number\" ||\n !Number.isFinite(\n input\n .captureTimeSecondsFromReference\n )\n ) {\n throw new InvalidScientificInputError(\n \"captureTimeSecondsFromReference must be finite.\"\n );\n }\n\n const {\n source,\n binding,\n waveform\n } =\n resolveSourceAndTemporalBinding(\n input.illuminationProfile,\n input.temporalProfile,\n input.sourceId\n );\n\n const waveformTimeSeconds =\n input\n .captureTimeSecondsFromReference -\n binding\n .waveformTimeZeroSecondsFromCaptureReference;\n const multiplier =\n evaluateWaveform(\n waveform,\n waveformTimeSeconds\n );\n\n return {\n sourceId: source.sourceId,\n sourceEnabled: source.enabled,\n temporalProfileId:\n input.temporalProfile.profileId,\n bindingId: binding.bindingId,\n waveformId: waveform.waveformId,\n captureTimeReference:\n \"first-opening-boundary-phase\",\n captureTimeSecondsFromReference:\n input\n .captureTimeSecondsFromReference,\n waveformTimeSecondsFromWaveformReference:\n waveformTimeSeconds,\n waveformKind: waveform.kind,\n relativeMagnitudeMultiplier:\n multiplier,\n effectiveRelativeMagnitudeMultiplier:\n source.enabled ? multiplier : 0,\n sourceMagnitudeApplied: false,\n materialTransportApplied: false,\n sceneRadianceCalculated: false,\n sensorReadoutTimingUsed: false,\n automaticExposureResolved: false\n };\n}\n\n/**\n * Integrates one source's time-varying multiplier over one local exposure window\n * (from sensor/exposure-window), using the deterministic midpoint rule.\n *\n * It integrates only the relative modulation over time. It does not apply source\n * magnitude, scene light transport, optics, sensor response or metering policy.\n */\nexport function integrateSceneIlluminationTemporalMultiplierOverExposureWindow(\n input:\n IntegrateSceneIlluminationTemporalMultiplierInput\n): SceneIlluminationTemporalExposureIntegration {\n requireInputKeys(input, \"integrateSceneIlluminationTemporalMultiplierOverExposureWindow\", [\"illuminationProfile\", \"temporalProfile\", \"sourceId\", \"exposureWindows\", \"sampleIndex\", \"temporalSampleCount\"]);\n requirePositiveInteger(\n \"temporalSampleCount\",\n input.temporalSampleCount\n );\n if (\n !Number.isSafeInteger(\n input.sampleIndex\n ) ||\n input.sampleIndex < 0\n ) {\n throw new InvalidScientificInputError(\n \"sampleIndex must be a non-negative safe integer.\"\n );\n }\n if (\n input.exposureWindows\n .timeReference !==\n \"first-opening-boundary-phase\"\n ) {\n throw new InvalidScientificInputError(\n \"Exposure windows must use the first-opening-boundary-phase time reference.\"\n );\n }\n\n const window =\n input.exposureWindows.samples[\n input.sampleIndex\n ];\n if (window === undefined) {\n throw new InvalidScientificInputError(\n \"sampleIndex is outside exposureWindows.samples.\"\n );\n }\n\n const context =\n resolveSourceAndTemporalBinding(\n input.illuminationProfile,\n input.temporalProfile,\n input.sourceId\n );\n const durationSeconds =\n window.localExposureDurationSeconds;\n const normalizedTimeWeight =\n 1 / input.temporalSampleCount;\n const timeMeasureSeconds =\n durationSeconds /\n input.temporalSampleCount;\n\n let averageMultiplier = 0;\n let integratedMultiplierSeconds =\n 0;\n let averageEffectiveMultiplier =\n 0;\n let integratedEffectiveMultiplierSeconds =\n 0;\n\n const nodes = Array.from(\n {\n length:\n input.temporalSampleCount\n },\n (_, temporalSampleIndex) => {\n const localExposurePhase =\n (temporalSampleIndex + 0.5) /\n input.temporalSampleCount;\n const captureTimeSeconds =\n window\n .startOffsetSecondsFromOpeningReference +\n localExposurePhase *\n durationSeconds;\n const evaluated =\n evaluateSceneIlluminationTemporalMultiplier(\n {\n illuminationProfile:\n input.illuminationProfile,\n temporalProfile:\n input.temporalProfile,\n sourceId: input.sourceId,\n captureTimeSecondsFromReference:\n captureTimeSeconds\n }\n );\n\n averageMultiplier +=\n evaluated\n .relativeMagnitudeMultiplier *\n normalizedTimeWeight;\n integratedMultiplierSeconds +=\n evaluated\n .relativeMagnitudeMultiplier *\n timeMeasureSeconds;\n averageEffectiveMultiplier +=\n evaluated\n .effectiveRelativeMagnitudeMultiplier *\n normalizedTimeWeight;\n integratedEffectiveMultiplierSeconds +=\n evaluated\n .effectiveRelativeMagnitudeMultiplier *\n timeMeasureSeconds;\n\n return {\n temporalSampleIndex,\n localExposurePhase,\n captureTimeSecondsFromReference:\n captureTimeSeconds,\n waveformTimeSecondsFromWaveformReference:\n evaluated\n .waveformTimeSecondsFromWaveformReference,\n relativeMagnitudeMultiplier:\n evaluated\n .relativeMagnitudeMultiplier,\n effectiveRelativeMagnitudeMultiplier:\n evaluated\n .effectiveRelativeMagnitudeMultiplier,\n normalizedTimeWeight,\n timeMeasureSeconds\n };\n }\n );\n\n return {\n sourceId: context.source.sourceId,\n sourceEnabled:\n context.source.enabled,\n temporalProfileId:\n input.temporalProfile.profileId,\n bindingId:\n context.binding.bindingId,\n waveformId:\n context.waveform.waveformId,\n timeReference:\n \"first-opening-boundary-phase\",\n localExposureWindow: {\n startSecondsFromCaptureReference:\n window\n .startOffsetSecondsFromOpeningReference,\n endSecondsFromCaptureReference:\n window\n .endOffsetSecondsFromOpeningReference,\n durationSeconds\n },\n quadratureScheme:\n \"uniform-midpoint\",\n temporalSampleCount:\n input.temporalSampleCount,\n nodes,\n averageRelativeMagnitudeMultiplier:\n averageMultiplier,\n integratedRelativeMagnitudeSeconds:\n integratedMultiplierSeconds,\n averageEffectiveRelativeMagnitudeMultiplier:\n averageEffectiveMultiplier,\n integratedEffectiveRelativeMagnitudeSeconds:\n integratedEffectiveMultiplierSeconds,\n sourceMagnitudeApplied: false,\n materialTransportApplied: false,\n sceneRadianceCalculated: false,\n sensorReadoutTimingUsed: false,\n automaticExposureResolved: false,\n convergenceErrorEstimated: false\n };\n}\n"]}
|
|
@@ -127,6 +127,7 @@ export interface SceneIlluminationProfile {
|
|
|
127
127
|
volumetricTransportModeled: false;
|
|
128
128
|
polarizationModeled: false;
|
|
129
129
|
}
|
|
130
|
+
export declare function parseVector3(value: unknown, path: string): Vector3;
|
|
130
131
|
/** Parses one source of a scene illumination profile (also used by record-taking helpers). Not a root export. */
|
|
131
132
|
export declare function parseSceneIlluminationSource(value: unknown, path: string): SceneIlluminationSource;
|
|
132
133
|
/**
|