@photivra/engine 2.18.0 → 2.20.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 +179 -1
- package/CITATION.cff +1 -1
- package/NODE_SUPPORT.md +7 -5
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +14 -10
- package/dist/capture/dng-lens-correction-opcodes.d.ts +32 -0
- package/dist/capture/dng-lens-correction-opcodes.js +119 -0
- package/dist/capture/dng-lens-correction-opcodes.js.map +1 -0
- 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 +2 -6
- 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/native-raw-dng.d.ts +6 -0
- package/dist/capture/native-raw-dng.js +16 -2
- package/dist/capture/native-raw-dng.js.map +1 -1
- package/dist/capture/release-sequence.js +2 -47
- package/dist/capture/release-sequence.js.map +1 -1
- package/dist/capture/sensor-raw-producer.js +3 -5
- package/dist/capture/sensor-raw-producer.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 +35 -0
- package/dist/core/shared-helpers.js +38 -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/generic-lens-catalogue.d.ts +8 -2
- package/dist/equipment/generic-lens-catalogue.js +31 -2
- package/dist/equipment/generic-lens-catalogue.js.map +1 -1
- package/dist/equipment/generic-tier-assets.js +2 -3
- package/dist/equipment/generic-tier-assets.js.map +1 -1
- package/dist/equipment/generic-tier-presets.js +2 -3
- package/dist/equipment/generic-tier-presets.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/display-view-gpu.d.ts +7 -4
- package/dist/facade/display-view-gpu.js +4 -4
- package/dist/facade/display-view-gpu.js.map +1 -1
- package/dist/facade/display-view-lens-signal.d.ts +1 -1
- package/dist/facade/display-view-lens-signal.js +5 -3
- package/dist/facade/display-view-lens-signal.js.map +1 -1
- package/dist/facade/display-view.d.ts +3 -1
- package/dist/facade/display-view.js +1 -1
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/fast-methods.d.ts +50 -0
- package/dist/facade/fast-methods.js +50 -0
- package/dist/facade/fast-methods.js.map +1 -0
- package/dist/facade/fast-resolution.d.ts +12 -0
- package/dist/facade/fast-resolution.js +18 -0
- package/dist/facade/fast-resolution.js.map +1 -0
- package/dist/facade/generic-lens-capture.d.ts +6 -3
- package/dist/facade/generic-lens-capture.js +6 -3
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +88 -16
- package/dist/facade/simulate-capture.js +279 -153
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.d.ts +3 -2
- package/dist/facade/simulate-display-view.js +22 -12
- package/dist/facade/simulate-display-view.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 +11 -1
- package/dist/index.js +8 -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/aperture-diameter.d.ts +47 -0
- package/dist/optics/aperture-diameter.js +50 -0
- package/dist/optics/aperture-diameter.js.map +1 -0
- 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/detail-limit.d.ts +182 -0
- package/dist/optics/detail-limit.js +336 -0
- package/dist/optics/detail-limit.js.map +1 -0
- 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-lens-psf.d.ts +18 -2
- package/dist/optics/generic-lens-psf.js +25 -2
- package/dist/optics/generic-lens-psf.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.d.ts +13 -0
- package/dist/optics/scene-to-sensor-irradiance.js +11 -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/crop-to-match-focal-length.d.ts +62 -0
- package/dist/output/crop-to-match-focal-length.js +63 -0
- package/dist/output/crop-to-match-focal-length.js.map +1 -0
- 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 +5 -7
- package/dist/output/generic-lens-corrections.js +11 -10
- 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/lens-corrections.d.ts +12 -2
- package/dist/output/lens-corrections.js +22 -7
- package/dist/output/lens-corrections.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/output/print-contrast-reference.js +1 -1
- package/dist/output/print-contrast-reference.js.map +1 -1
- package/dist/output/print-size-blur-noise.d.ts +110 -0
- package/dist/output/print-size-blur-noise.js +138 -0
- package/dist/output/print-size-blur-noise.js.map +1 -0
- 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 -41
- package/dist/sensor/eqe-electron-rate.js.map +1 -1
- package/dist/sensor/exposure-window.d.ts +7 -0
- package/dist/sensor/exposure-window.js +9 -24
- 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 +4 -79
- 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 +4 -35
- 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 -114
- 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/sensor-characteristics.d.ts +137 -0
- package/dist/sensor/sensor-characteristics.js +115 -0
- package/dist/sensor/sensor-characteristics.js.map +1 -0
- package/dist/sensor/spatial-sample-reduction.js +3 -24
- 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 +3 -41
- 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/sensor/temporal-photo-signal.d.ts +3 -0
- package/dist/sensor/temporal-photo-signal.js +5 -2
- package/dist/sensor/temporal-photo-signal.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.d.ts +9 -0
- package/dist/stabilization/system.js +7 -86
- package/dist/stabilization/system.js.map +1 -1
- package/docs/AGENT_GUIDE.md +5 -0
- package/docs/API_REFERENCE.md +116 -3
- package/docs/QUICK_START.md +178 -14
- package/docs/USAGE.md +111 -3
- package/docs/api/capture-native-raw-dng.md +6 -0
- package/docs/api/core-version.md +1 -1
- package/docs/api/equipment-generic-lens-catalogue.md +7 -2
- package/docs/api/exports.json +203 -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-display-view-gpu.md +5 -2
- package/docs/api/facade-fast-methods.md +91 -0
- package/docs/api/facade-simulate-capture.md +72 -16
- package/docs/api/facade-simulate-display-view.md +3 -2
- package/docs/api/optics-aperture-diameter.md +51 -0
- package/docs/api/optics-detail-limit.md +203 -0
- 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-crop-to-match-focal-length.md +67 -0
- package/docs/api/output-developed-lens-corrections.md +12 -0
- package/docs/api/output-generic-lens-corrections.md +3 -10
- package/docs/api/output-lens-corrections.md +11 -1
- package/docs/api/output-print-size-blur-noise.md +115 -0
- package/docs/api/sensor-sensor-characteristics.md +105 -0
- package/llms.txt +5 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"focus-state.js","sourceRoot":"","sources":["../../src/optics/focus-state.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,gBAAgB,EAEjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EACL,8BAA8B,EAE/B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"focus-state.js","sourceRoot":"","sources":["../../src/optics/focus-state.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,gBAAgB,EAEjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EACL,8BAA8B,EAE/B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,IAAI,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAyBtG;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAEzE,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,IAAI,yBAAyB,CACjC,uDAAuD,CACxD,CAAC;QACJ,CAAC;QACD,OAAO;YACL,IAAI,EAAE,UAAU;SACjB,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,IACE,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ;YACpC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;YAClC,MAAM,CAAC,SAAS,IAAI,CAAC,EACrB,CAAC;YACD,MAAM,IAAI,yBAAyB,CACjC,iEAAiE,CAClE,CAAC;QACJ,CAAC;QACD,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,MAAM,CAAC,SAAS;SAC5B,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,yBAAyB,CACjC,iDAAiD,CAClD,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gCAAgC,CAC9C,KAA4C;IAE5C,gBAAgB,CAAC,KAAK,EAAE,kCAAkC,EAAE,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC;IACxF,qBAAqB,CAAC,eAAe,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAE5D,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAE3C,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,8BAA8B,CAAC;YACpC,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,eAAe,EAAE,KAAK,CAAC,SAAS;SACjC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,gBAAgB,CACrB;QACE,eAAe,EAAE,KAAK,CAAC,aAAa;QACpC,aAAa,EAAE,CAAC;QAChB,uBAAuB,EAAE,CAAC;KAC3B,EACD,qCAAqC,EACrC,OAAO,EACP;QACE,6CAA6C;QAC7C,gEAAgE;QAChE,yFAAyF;KAC1F,CACF,CAAC;AACJ,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Explicit focus state: a finite focus distance, or infinity.\n *\n * The parser reads the state from untrusted JSON. Missing or unknown focus is rejected; it is never\n * read as infinity.\n *\n * The image-distance function uses the existing Gaussian thin-lens calculation for finite focus, so\n * its numbers and provenance are unchanged. Infinity focus gives exactly the nominal focal length,\n * with a limiting magnification of zero.\n * @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport {\n calculatedResult,\n type CalculationResult\n} from \"../core/calculation-result.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requirePositiveFinite } from \"../core/validation.js\";\nimport {\n calculateThinLensImageDistance,\n type ThinLensImageDistance\n} from \"./thin-lens.js\";\nimport { requireInputKeys, requireConfigRecord as requireRecord } from \"../core/record-validation.js\";\n\n/**\n * Explicit ideal focus-plane state.\n *\n * A finite distance is measured along the camera's optical axis, from the\n * ideal lens principal plane to the object plane. Infinity is a named state.\n * It is never stored as JavaScript Infinity or as a made-up large distance.\n */\nexport type FocusPlane =\n | {\n kind: \"finite\";\n distanceM: number;\n }\n | {\n kind: \"infinity\";\n };\n\nexport interface CalculateFocusPlaneImageDistanceInput {\n /** Lens focal length in millimetres. */\n focalLengthMm: number;\n /** Explicit finite or infinity focus-plane state. */\n focus: FocusPlane;\n}\n\n/**\n * Parses an explicit focus-plane state from untrusted JSON.\n *\n * Missing or unknown focus is rejected. It is never read as infinity.\n */\nexport function parseFocusPlane(value: unknown): FocusPlane {\n const record = requireRecord(value, \"focusPlane\", [\"kind\", \"distanceM\"]);\n\n if (record.kind === \"infinity\") {\n if (record.distanceM !== undefined) {\n throw new InvalidConfigurationError(\n \"focusPlane infinity state must not include distanceM.\"\n );\n }\n return {\n kind: \"infinity\"\n };\n }\n\n if (record.kind === \"finite\") {\n if (\n typeof record.distanceM !== \"number\" ||\n !Number.isFinite(record.distanceM) ||\n record.distanceM <= 0\n ) {\n throw new InvalidConfigurationError(\n \"focusPlane.distanceM must be a finite number greater than zero.\"\n );\n }\n return {\n kind: \"finite\",\n distanceM: record.distanceM\n };\n }\n\n throw new InvalidConfigurationError(\n 'focusPlane.kind must be \"finite\" or \"infinity\".'\n );\n}\n\n/**\n * Calculates the ideal image-plane distance for an explicit focus state.\n *\n * Finite focus uses the existing Gaussian thin-lens calculation, so its\n * numbers and provenance are unchanged. Infinity focus gives exactly the\n * nominal focal length, with a limiting magnification of zero.\n */\nexport function calculateFocusPlaneImageDistance(\n input: CalculateFocusPlaneImageDistanceInput\n): CalculationResult<ThinLensImageDistance> {\n requireInputKeys(input, \"calculateFocusPlaneImageDistance\", [\"focalLengthMm\", \"focus\"]);\n requirePositiveFinite(\"focalLengthMm\", input.focalLengthMm);\n\n const focus = parseFocusPlane(input.focus);\n\n if (focus.kind === \"finite\") {\n return calculateThinLensImageDistance({\n focalLengthMm: input.focalLengthMm,\n objectDistanceM: focus.distanceM\n });\n }\n\n return calculatedResult(\n {\n imageDistanceMm: input.focalLengthMm,\n magnification: 0,\n infinityProjectionScale: 1\n },\n \"ideal-infinity-focus-image-distance\",\n \"1.0.0\",\n [\n \"Paraxial ideal-lens infinity-focus boundary\",\n \"Image distance equals nominal focal length at optical infinity\",\n \"Infinity is represented semantically rather than by a non-finite or fabricated distance\"\n ]\n );\n}\n"]}
|
|
@@ -123,6 +123,11 @@ export interface ComposedFrontOfLensFilterTransmission {
|
|
|
123
123
|
sensorOpticalStackIncluded: false;
|
|
124
124
|
fieldThroughputIncluded: false;
|
|
125
125
|
}
|
|
126
|
+
export declare function parseRange(value: unknown, path: string): {
|
|
127
|
+
minimum: number;
|
|
128
|
+
maximum: number;
|
|
129
|
+
};
|
|
130
|
+
export declare function parseResolvedBasis(value: unknown, path: string): Exclude<SpectralWavelengthBasis, "unspecified">;
|
|
126
131
|
/**
|
|
127
132
|
* Parses one generic front-of-lens transmission filter.
|
|
128
133
|
*
|
|
@@ -26,50 +26,10 @@ import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
|
26
26
|
import { parseEvidenceList } from "../core/evidence-provenance.js";
|
|
27
27
|
import { parseSpectralWavelengthBasis } from "../core/spectral.js";
|
|
28
28
|
import { InvalidScientificInputError } from "../core/validation.js";
|
|
29
|
-
import { requireInputKeys,
|
|
29
|
+
import { requireInputKeys, rejectUnknownVariantFields, UNCERTAINTY_VARIANT_FIELDS, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, requireConfigFinite as requireFinite, parseConfigScientificStatus as parseScientificStatus, parseConfigLimitations as parseLimitations, requireConfigFiniteAboveZero as requirePositiveFinite, requireConfigFiniteAtLeastZero as requireNonNegativeFinite } from "../core/record-validation.js";
|
|
30
30
|
export const FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION = "0.1.0";
|
|
31
31
|
/** Schema that also allows the `linear-polarizer` transmission kind. */
|
|
32
32
|
export const FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION = "0.2.0";
|
|
33
|
-
function requireRecord(value, path, allowedKeys) {
|
|
34
|
-
if (typeof value !== "object" ||
|
|
35
|
-
value === null ||
|
|
36
|
-
Array.isArray(value)) {
|
|
37
|
-
throw new InvalidConfigurationError(path + " must be an object.");
|
|
38
|
-
}
|
|
39
|
-
if (allowedKeys !== null)
|
|
40
|
-
rejectUnknownFields(value, allowedKeys, path);
|
|
41
|
-
return value;
|
|
42
|
-
}
|
|
43
|
-
function requireNonEmptyString(value, path) {
|
|
44
|
-
if (typeof value !== "string" ||
|
|
45
|
-
value.trim().length === 0) {
|
|
46
|
-
throw new InvalidConfigurationError(path + " must be a non-empty string.");
|
|
47
|
-
}
|
|
48
|
-
return value.trim();
|
|
49
|
-
}
|
|
50
|
-
function requireFinite(value, path) {
|
|
51
|
-
if (typeof value !== "number" ||
|
|
52
|
-
!Number.isFinite(value)) {
|
|
53
|
-
throw new InvalidConfigurationError(path + " must be finite.");
|
|
54
|
-
}
|
|
55
|
-
return value;
|
|
56
|
-
}
|
|
57
|
-
function requirePositiveFinite(value, path) {
|
|
58
|
-
const parsed = requireFinite(value, path);
|
|
59
|
-
if (parsed <= 0) {
|
|
60
|
-
throw new InvalidConfigurationError(path +
|
|
61
|
-
" must be greater than zero.");
|
|
62
|
-
}
|
|
63
|
-
return parsed;
|
|
64
|
-
}
|
|
65
|
-
function requireNonNegativeFinite(value, path) {
|
|
66
|
-
const parsed = requireFinite(value, path);
|
|
67
|
-
if (parsed < 0) {
|
|
68
|
-
throw new InvalidConfigurationError(path +
|
|
69
|
-
" must be greater than or equal to zero.");
|
|
70
|
-
}
|
|
71
|
-
return parsed;
|
|
72
|
-
}
|
|
73
33
|
function requirePassiveTransmission(value, path) {
|
|
74
34
|
const parsed = requirePositiveFinite(value, path);
|
|
75
35
|
if (parsed > 1) {
|
|
@@ -78,7 +38,7 @@ function requirePassiveTransmission(value, path) {
|
|
|
78
38
|
}
|
|
79
39
|
return parsed;
|
|
80
40
|
}
|
|
81
|
-
function parseRange(value, path) {
|
|
41
|
+
export function parseRange(value, path) {
|
|
82
42
|
const record = requireRecord(value, path, ["minimum", "maximum"]);
|
|
83
43
|
const minimum = requirePositiveFinite(record.minimum, path + ".minimum");
|
|
84
44
|
const maximum = requirePositiveFinite(record.maximum, path + ".maximum");
|
|
@@ -91,7 +51,7 @@ function parseRange(value, path) {
|
|
|
91
51
|
maximum
|
|
92
52
|
};
|
|
93
53
|
}
|
|
94
|
-
function parseResolvedBasis(value, path) {
|
|
54
|
+
export function parseResolvedBasis(value, path) {
|
|
95
55
|
const parsed = parseSpectralWavelengthBasis(value, path);
|
|
96
56
|
if (parsed === "unspecified") {
|
|
97
57
|
throw new InvalidConfigurationError(path +
|
|
@@ -99,13 +59,6 @@ function parseResolvedBasis(value, path) {
|
|
|
99
59
|
}
|
|
100
60
|
return parsed;
|
|
101
61
|
}
|
|
102
|
-
function parseScientificStatus(value, path) {
|
|
103
|
-
if (value !== "calibrated" &&
|
|
104
|
-
value !== "approximation") {
|
|
105
|
-
throw new InvalidConfigurationError(path + " is invalid.");
|
|
106
|
-
}
|
|
107
|
-
return value;
|
|
108
|
-
}
|
|
109
62
|
function parseUncertainty(value, path) {
|
|
110
63
|
const record = requireRecord(value, path, null);
|
|
111
64
|
rejectUnknownVariantFields(record, "kind", UNCERTAINTY_VARIANT_FIELDS, path);
|
|
@@ -130,21 +83,6 @@ function parseUncertainty(value, path) {
|
|
|
130
83
|
}
|
|
131
84
|
throw new InvalidConfigurationError(path + ".kind is invalid.");
|
|
132
85
|
}
|
|
133
|
-
function parseLimitations(value, path) {
|
|
134
|
-
if (!Array.isArray(value)) {
|
|
135
|
-
throw new InvalidConfigurationError(path + " must be an array.");
|
|
136
|
-
}
|
|
137
|
-
const parsed = value.map((entry, index) => requireNonEmptyString(entry, path +
|
|
138
|
-
"[" +
|
|
139
|
-
index +
|
|
140
|
-
"]"));
|
|
141
|
-
if (new Set(parsed).size !==
|
|
142
|
-
parsed.length) {
|
|
143
|
-
throw new InvalidConfigurationError(path +
|
|
144
|
-
" must not contain duplicates.");
|
|
145
|
-
}
|
|
146
|
-
return parsed;
|
|
147
|
-
}
|
|
148
86
|
function parseReusableNumericEvidence(value, path) {
|
|
149
87
|
const evidence = parseEvidenceList(value, path);
|
|
150
88
|
if (evidence.some((entry) => entry.reuseStatus ===
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"front-of-lens-filter.js","sourceRoot":"","sources":["../../src/optics/front-of-lens-filter.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Generic filters that screw onto the front of the lens.\n *\n * Schema 0.1.0 is explicitly unbranded and unpolarized. It models only passive transmission in front\n * of the lens. It does not cover reflections between stacked filters, flare or ghosting, or filters\n * that change wavelength.\n *\n * Schema 0.2.0 adds one polarizing kind: a linear (partial) polarizer. It has a principal\n * transmittance k1, an extinction ratio k1/k2 and a transmission-axis angle. Polarization is carried\n * as linear Stokes parameters (S0, S1, S2). Filters are applied in order using the Mueller matrix of\n * a linear diattenuator (Gil, arXiv:2002.04105, eqs. 134-135, free; Malus's law: OpenStax University\n * Physics Vol. 3, sec. 1.7, free. Also see: Chipman, Handbook of Optics vol. I ch. 22, 3rd ed., 2010;\n * Goldstein, Polarized Light, 3rd ed., ch. 4-5; Born & Wolf, Principles of Optics, sec. 1.4.2):\n * T = (k1 + k2)/2 + (k1 - k2)/2 * P * cos(2 (psi - theta))\n * Here P is the incident light's degree of linear polarization, psi its polarization angle and theta\n * the filter axis angle.\n * - For P = 1 this is Malus's law: k1 cos^2(psi - theta) + k2 sin^2(psi - theta).\n * - For unpolarized light it is (k1 + k2)/2, about half of k1.\n * Not modelled: circular polarization, retardance (for example the quarter-wave plate in a circular\n * polarizer), dependence on the angle of incidence, and depolarization.\n * @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceBackedFact,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport {\n parseSpectralWavelengthBasis,\n type SpectralWavelengthBasis\n} from \"../core/spectral.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport { requireInputKeys, rejectUnknownFields, rejectUnknownVariantFields, UNCERTAINTY_VARIANT_FIELDS } from \"../core/record-validation.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport const FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION =\n \"0.1.0\" as const;\n/** Schema that also allows the `linear-polarizer` transmission kind. */\nexport const FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION =\n \"0.2.0\" as const;\n\nexport type FrontOfLensFilterProfileSchemaVersion =\n | typeof FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION\n | typeof FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION;\n\n/** Partially linearly polarized light: degree P in [0, 1] and polarization angle psi. */\nexport interface LinearPolarizationState {\n /** Degree of linear polarization P in [0, 1]; 0 is unpolarized. */\n degreeOfLinearPolarization: number;\n /** Electric-field polarization angle, degrees counter-clockwise from image +X. */\n angleDegrees: number;\n}\n\nexport type FrontOfLensFilterScientificStatus =\n | \"calibrated\"\n | \"approximation\";\n\nexport type FrontOfLensFilterUncertainty =\n | {\n kind: \"relative\";\n fraction: number;\n basis: string;\n }\n | {\n kind: \"not-quantified\";\n limitation: string;\n };\n\nexport interface FrontOfLensFilterSpectralSample {\n wavelengthNanometers: number;\n linearTransmissionFactor: number;\n}\n\nexport type FrontOfLensFilterTransmissionModel =\n | {\n kind: \"neutral-linear-transmission\";\n linearTransmissionFactor:\n EvidenceBackedFact<number>;\n }\n | {\n kind: \"neutral-optical-density\";\n opticalDensityBase10:\n EvidenceBackedFact<number>;\n }\n | {\n kind: \"spectral-transmission\";\n samples:\n EvidenceBackedFact<\n readonly FrontOfLensFilterSpectralSample[]\n >;\n }\n | {\n /** Schema 0.2.0 only. Neutral (wavelength-independent) within the declared range. */\n kind: \"linear-polarizer\";\n /** k1: intensity transmittance for light polarized along the transmission axis, (0, 1]. */\n principalTransmittance:\n EvidenceBackedFact<number>;\n /** k1 / k2. Finite and >= 1. Use a large finite ratio for a near-ideal polarizer. */\n extinctionRatio:\n EvidenceBackedFact<number>;\n /** Transmission-axis angle as mounted, degrees counter-clockwise from image +X. */\n transmissionAxisDegrees: number;\n };\n\nexport interface FrontOfLensFilterProfile {\n schemaVersion:\n FrontOfLensFilterProfileSchemaVersion;\n filterId: string;\n profileVersion: string;\n identityScope:\n \"photivra-generic-unbranded\";\n position: \"front-of-lens\";\n scientificStatus:\n FrontOfLensFilterScientificStatus;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n wavelengthRangeNanometers: {\n minimum: number;\n maximum: number;\n };\n transmission:\n FrontOfLensFilterTransmissionModel;\n uncertainty:\n FrontOfLensFilterUncertainty;\n /** True exactly when the transmission kind is `linear-polarizer` (schema 0.2.0). */\n polarizationModeled: boolean;\n wavelengthChangingBehaviorModeled:\n false;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface ResolveFrontOfLensFilterTransmissionInput {\n profile: FrontOfLensFilterProfile;\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n /** Incident polarization; omitted means unpolarized. */\n incidentPolarization?: LinearPolarizationState;\n}\n\nexport interface ResolvedFrontOfLensFilterTransmission {\n schemaVersion:\n FrontOfLensFilterProfileSchemaVersion;\n filterId: string;\n profileVersion: string;\n identityScope:\n \"photivra-generic-unbranded\";\n position: \"front-of-lens\";\n scientificStatus:\n FrontOfLensFilterScientificStatus;\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n transmissionKind:\n FrontOfLensFilterTransmissionModel[\"kind\"];\n /** Intensity transmittance for the declared incident polarization. */\n linearTransmissionFactor: number;\n attenuationStops: number;\n opticalDensityBase10: number;\n polarizationModeled: boolean;\n incidentPolarization: LinearPolarizationState;\n transmittedPolarization: LinearPolarizationState;\n wavelengthChangingBehaviorModeled:\n false;\n lensTransmissionIncluded: false;\n sensorOpticalStackIncluded: false;\n fieldThroughputIncluded: false;\n uncertainty:\n FrontOfLensFilterUncertainty;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface ComposeFrontOfLensFilterTransmissionInput {\n /** Filters in light-path order (scene side first). */\n filters:\n readonly FrontOfLensFilterProfile[];\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n /** Incident scene polarization; omitted means unpolarized. */\n incidentPolarization?: LinearPolarizationState;\n}\n\nexport interface ComposedFrontOfLensFilterTransmission {\n schemaVersion:\n FrontOfLensFilterProfileSchemaVersion;\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n appliedFilterCount: number;\n components:\n readonly ResolvedFrontOfLensFilterTransmission[];\n combinedLinearTransmissionFactor:\n number;\n combinedAttenuationStops: number;\n scientificStatus:\n FrontOfLensFilterScientificStatus;\n uncertaintyPropagation:\n \"not-propagated\";\n uncertaintyLimitation: string;\n compositionModel:\n | \"independent-multiplicative-unpolarized-transmission-no-inter-filter-reflections\"\n | \"ordered-linear-stokes-mueller-no-inter-filter-reflections\";\n polarizationModeled: boolean;\n incidentPolarization: LinearPolarizationState;\n transmittedPolarization: LinearPolarizationState;\n wavelengthChangingBehaviorModeled:\n false;\n lensTransmissionIncluded: false;\n sensorOpticalStackIncluded: false;\n fieldThroughputIncluded: 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 requirePassiveTransmission(\n value: unknown,\n path: string\n): number {\n const parsed = requirePositiveFinite(\n value,\n path\n );\n if (parsed > 1) {\n throw new InvalidConfigurationError(\n path +\n \" must be less than or equal to one for a passive filter.\"\n );\n }\n return parsed;\n}\n\nfunction parseRange(\n value: unknown,\n path: string\n): {\n minimum: number;\n maximum: number;\n} {\n const record = requireRecord(\n value,\n path, [\"minimum\", \"maximum\"]\n );\n const minimum =\n requirePositiveFinite(\n record.minimum,\n path + \".minimum\"\n );\n const maximum =\n requirePositiveFinite(\n record.maximum,\n path + \".maximum\"\n );\n if (minimum > maximum) {\n throw new InvalidConfigurationError(\n path +\n \".minimum must be less than or equal to maximum.\"\n );\n }\n return {\n minimum,\n maximum\n };\n}\n\nfunction parseResolvedBasis(\n value: unknown,\n path: string\n): Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n> {\n const parsed =\n parseSpectralWavelengthBasis(\n value,\n path\n );\n if (parsed === \"unspecified\") {\n throw new InvalidConfigurationError(\n path +\n ' must resolve to \"air\" or \"vacuum\".'\n );\n }\n return parsed;\n}\n\nfunction parseScientificStatus(\n value: unknown,\n path: string\n): FrontOfLensFilterScientificStatus {\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): FrontOfLensFilterUncertainty {\n const record = requireRecord(\n value,\n path, null\n );\n rejectUnknownVariantFields(record, \"kind\", UNCERTAINTY_VARIANT_FIELDS, path);\n\n if (record.kind === \"relative\") {\n const fraction =\n requireNonNegativeFinite(\n record.fraction,\n path + \".fraction\"\n );\n if (fraction > 1) {\n throw new InvalidConfigurationError(\n path +\n \".fraction must be less than or equal to one.\"\n );\n }\n return {\n kind: \"relative\",\n fraction,\n basis:\n requireNonEmptyString(\n record.basis,\n path + \".basis\"\n )\n };\n }\n\n if (\n record.kind ===\n \"not-quantified\"\n ) {\n return {\n kind: \"not-quantified\",\n limitation:\n requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseLimitations(\n value: unknown,\n path: string\n): readonly string[] {\n if (!Array.isArray(value)) {\n throw new InvalidConfigurationError(\n path + \" must be an array.\"\n );\n }\n const parsed = value.map(\n (entry, index) =>\n requireNonEmptyString(\n entry,\n path +\n \"[\" +\n index +\n \"]\"\n )\n );\n if (\n new Set(parsed).size !==\n parsed.length\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must not contain duplicates.\"\n );\n }\n return parsed;\n}\n\nfunction parseReusableNumericEvidence(\n value: unknown,\n path: string\n): readonly EvidenceProvenance[] {\n const evidence =\n parseEvidenceList(\n value,\n path\n );\n if (\n evidence.some(\n (entry) =>\n entry.reuseStatus ===\n \"factual-reference-only\"\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \" for embedded numeric filter data must be reusable-data or photivra-owned.\"\n );\n }\n return evidence;\n}\n\nfunction parseSpectralSamples(\n value: unknown,\n path: string\n): readonly FrontOfLensFilterSpectralSample[] {\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(\n (entry, index) => {\n const samplePath =\n path +\n \"[\" +\n index +\n \"]\";\n const record =\n requireRecord(\n entry,\n samplePath, [\"wavelengthNanometers\", \"linearTransmissionFactor\"]\n );\n const wavelengthNanometers =\n requirePositiveFinite(\n record.wavelengthNanometers,\n samplePath +\n \".wavelengthNanometers\"\n );\n if (\n wavelengthNanometers <=\n previous\n ) {\n throw new InvalidConfigurationError(\n path +\n \" wavelengths must be strictly increasing.\"\n );\n }\n previous =\n wavelengthNanometers;\n return {\n wavelengthNanometers,\n linearTransmissionFactor:\n requirePassiveTransmission(\n record.linearTransmissionFactor,\n samplePath +\n \".linearTransmissionFactor\"\n )\n };\n }\n );\n}\n\nfunction parseTransmission(\n value: unknown,\n path: string,\n polarizerAllowed: boolean\n): FrontOfLensFilterTransmissionModel {\n const record = requireRecord(\n value,\n path, null\n );\n rejectUnknownVariantFields(record, \"kind\", {\n \"neutral-linear-transmission\": [\"kind\", \"linearTransmissionFactor\"],\n \"neutral-optical-density\": [\"kind\", \"opticalDensityBase10\"],\n \"spectral-transmission\": [\"kind\", \"samples\"],\n \"linear-polarizer\": [\"kind\", \"principalTransmittance\", \"extinctionRatio\", \"transmissionAxisDegrees\"]\n }, path);\n\n if (record.kind === \"linear-polarizer\") {\n if (!polarizerAllowed) {\n throw new InvalidConfigurationError(\n path + '.kind \"linear-polarizer\" requires schemaVersion \"' +\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION + '\".'\n );\n }\n const principal = requireRecord(\n record.principalTransmittance,\n path + \".principalTransmittance\", [\"value\", \"evidence\"]\n );\n const extinction = requireRecord(\n record.extinctionRatio,\n path + \".extinctionRatio\", [\"value\", \"evidence\"]\n );\n const ratio = requireFinite(\n extinction.value,\n path + \".extinctionRatio.value\"\n );\n if (ratio < 1) {\n throw new InvalidConfigurationError(\n path + \".extinctionRatio.value must be at least one.\"\n );\n }\n return {\n kind: \"linear-polarizer\",\n principalTransmittance: {\n value: requirePassiveTransmission(\n principal.value,\n path + \".principalTransmittance.value\"\n ),\n evidence: parseEvidenceList(\n principal.evidence,\n path + \".principalTransmittance.evidence\"\n )\n },\n extinctionRatio: {\n value: ratio,\n evidence: parseEvidenceList(\n extinction.evidence,\n path + \".extinctionRatio.evidence\"\n )\n },\n transmissionAxisDegrees: requireFinite(\n record.transmissionAxisDegrees,\n path + \".transmissionAxisDegrees\"\n )\n };\n }\n\n if (\n record.kind ===\n \"neutral-linear-transmission\"\n ) {\n const fact = requireRecord(\n record.linearTransmissionFactor,\n path +\n \".linearTransmissionFactor\", [\"value\", \"evidence\"]\n );\n return {\n kind:\n \"neutral-linear-transmission\",\n linearTransmissionFactor: {\n value:\n requirePassiveTransmission(\n fact.value,\n path +\n \".linearTransmissionFactor.value\"\n ),\n evidence:\n parseEvidenceList(\n fact.evidence,\n path +\n \".linearTransmissionFactor.evidence\"\n )\n }\n };\n }\n\n if (\n record.kind ===\n \"neutral-optical-density\"\n ) {\n const fact = requireRecord(\n record.opticalDensityBase10,\n path +\n \".opticalDensityBase10\", [\"value\", \"evidence\"]\n );\n return {\n kind:\n \"neutral-optical-density\",\n opticalDensityBase10: {\n value:\n requireNonNegativeFinite(\n fact.value,\n path +\n \".opticalDensityBase10.value\"\n ),\n evidence:\n parseEvidenceList(\n fact.evidence,\n path +\n \".opticalDensityBase10.evidence\"\n )\n }\n };\n }\n\n if (\n record.kind ===\n \"spectral-transmission\"\n ) {\n const fact = requireRecord(\n record.samples,\n path + \".samples\", [\"value\", \"evidence\"]\n );\n return {\n kind:\n \"spectral-transmission\",\n samples: {\n value:\n parseSpectralSamples(\n fact.value,\n path +\n \".samples.value\"\n ),\n evidence:\n parseReusableNumericEvidence(\n fact.evidence,\n path +\n \".samples.evidence\"\n )\n }\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\n/**\n * Parses one generic front-of-lens transmission filter.\n *\n * Schema 0.1.0 is explicitly unbranded and unpolarized. It models only\n * passive transmission in front of the lens. It does not cover reflections\n * between stacked filters, polarization, flare or ghosting, or filters that\n * change wavelength.\n */\nexport function parseFrontOfLensFilterProfile(\n value: unknown\n): FrontOfLensFilterProfile {\n const record = requireRecord(\n value,\n \"frontOfLensFilterProfile\", [\"schemaVersion\", \"identityScope\", \"position\", \"wavelengthChangingBehaviorModeled\", \"polarizationModeled\", \"scientificStatus\", \"uncertainty\", \"wavelengthRangeNanometers\", \"transmission\", \"filterId\", \"profileVersion\", \"wavelengthBasis\", \"evidence\", \"limitations\"]\n );\n\n if (\n record.schemaVersion !==\n FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION &&\n record.schemaVersion !==\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'frontOfLensFilterProfile.schemaVersion must be \"' +\n FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION +\n '\" or \"' +\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n const schemaVersion =\n record.schemaVersion as FrontOfLensFilterProfileSchemaVersion;\n if (\n record.identityScope !==\n \"photivra-generic-unbranded\"\n ) {\n throw new InvalidConfigurationError(\n 'frontOfLensFilterProfile.identityScope must be \"photivra-generic-unbranded\".'\n );\n }\n if (\n record.position !==\n \"front-of-lens\"\n ) {\n throw new InvalidConfigurationError(\n 'frontOfLensFilterProfile.position must be \"front-of-lens\".'\n );\n }\n if (\n record.wavelengthChangingBehaviorModeled !==\n false ||\n (schemaVersion ===\n FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION &&\n record.polarizationModeled !== false)\n ) {\n throw new InvalidConfigurationError(\n \"frontOfLensFilterProfile must explicitly keep polarization and wavelength-changing behavior unmodeled in schema 0.1.0.\"\n );\n }\n\n const status =\n parseScientificStatus(\n record.scientificStatus,\n \"frontOfLensFilterProfile.scientificStatus\"\n );\n const uncertainty =\n parseUncertainty(\n record.uncertainty,\n \"frontOfLensFilterProfile.uncertainty\"\n );\n\n if (\n status === \"calibrated\" &&\n uncertainty.kind !==\n \"relative\"\n ) {\n throw new InvalidConfigurationError(\n \"A calibrated filter profile requires quantified relative uncertainty.\"\n );\n }\n\n const range =\n parseRange(\n record.wavelengthRangeNanometers,\n \"frontOfLensFilterProfile.wavelengthRangeNanometers\"\n );\n const transmission =\n parseTransmission(\n record.transmission,\n \"frontOfLensFilterProfile.transmission\",\n schemaVersion ===\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION\n );\n const polarizationModeled =\n transmission.kind === \"linear-polarizer\";\n if (record.polarizationModeled !== polarizationModeled) {\n throw new InvalidConfigurationError(\n \"frontOfLensFilterProfile.polarizationModeled must be true exactly for a linear-polarizer transmission.\"\n );\n }\n\n if (\n transmission.kind ===\n \"spectral-transmission\"\n ) {\n const samples =\n transmission.samples.value;\n if (\n samples[0]!\n .wavelengthNanometers >\n range.minimum ||\n samples[\n samples.length - 1\n ]!.wavelengthNanometers <\n range.maximum\n ) {\n throw new InvalidConfigurationError(\n \"Spectral filter samples must cover the declared wavelength range.\"\n );\n }\n }\n\n return {\n schemaVersion,\n filterId:\n requireNonEmptyString(\n record.filterId,\n \"frontOfLensFilterProfile.filterId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"frontOfLensFilterProfile.profileVersion\"\n ),\n identityScope:\n \"photivra-generic-unbranded\",\n position:\n \"front-of-lens\",\n scientificStatus:\n status,\n wavelengthBasis:\n parseResolvedBasis(\n record.wavelengthBasis,\n \"frontOfLensFilterProfile.wavelengthBasis\"\n ),\n wavelengthRangeNanometers:\n range,\n transmission,\n uncertainty,\n polarizationModeled,\n wavelengthChangingBehaviorModeled:\n false,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"frontOfLensFilterProfile.evidence\"\n ),\n limitations:\n parseLimitations(\n record.limitations,\n \"frontOfLensFilterProfile.limitations\"\n )\n };\n}\n\nfunction interpolateSpectralTransmission(\n samples:\n readonly FrontOfLensFilterSpectralSample[],\n wavelengthNanometers: number\n): number {\n const first =\n samples[0]!;\n const last =\n samples[\n samples.length - 1\n ]!;\n\n if (\n wavelengthNanometers ===\n first.wavelengthNanometers\n ) {\n return first\n .linearTransmissionFactor;\n }\n\n for (\n let index = 1;\n index < samples.length;\n index += 1\n ) {\n const right =\n samples[index]!;\n if (\n wavelengthNanometers <=\n right.wavelengthNanometers\n ) {\n const left =\n samples[\n index - 1\n ]!;\n if (\n wavelengthNanometers ===\n right.wavelengthNanometers\n ) {\n return right\n .linearTransmissionFactor;\n }\n const phase =\n (wavelengthNanometers -\n left.wavelengthNanometers) /\n (right.wavelengthNanometers -\n left.wavelengthNanometers);\n return (\n left\n .linearTransmissionFactor +\n phase *\n (right\n .linearTransmissionFactor -\n left\n .linearTransmissionFactor)\n );\n }\n }\n\n return last\n .linearTransmissionFactor;\n}\n\nfunction scientificWavelength(\n value: number\n): number {\n if (\n !Number.isFinite(value) ||\n value <= 0\n ) {\n throw new InvalidScientificInputError(\n \"wavelengthNanometers must be finite and greater than zero.\"\n );\n }\n return value;\n}\n\nfunction transmissionEvidence(\n transmission:\n FrontOfLensFilterTransmissionModel\n): readonly EvidenceProvenance[] {\n if (\n transmission.kind ===\n \"neutral-linear-transmission\"\n ) {\n return transmission\n .linearTransmissionFactor\n .evidence;\n }\n if (\n transmission.kind ===\n \"neutral-optical-density\"\n ) {\n return transmission\n .opticalDensityBase10\n .evidence;\n }\n if (transmission.kind === \"linear-polarizer\") {\n return [\n ...transmission.principalTransmittance.evidence,\n ...transmission.extinctionRatio.evidence\n ];\n }\n return transmission\n .samples.evidence;\n}\n\n/** Linear Stokes vector (S0, S1, S2); circular S3 is not modeled. */\ninterface LinearStokes {\n s0: number;\n s1: number;\n s2: number;\n}\n\nconst UNPOLARIZED: LinearPolarizationState = /* @__PURE__ */ Object.freeze({\n degreeOfLinearPolarization: 0,\n angleDegrees: 0\n});\n\nfunction parsePolarizationState(\n value: LinearPolarizationState | undefined,\n path: string\n): LinearPolarizationState {\n if (value === undefined) {\n return { ...UNPOLARIZED };\n }\n if (typeof value !== \"object\" || value === null) {\n throw new InvalidConfigurationError(path + \" must be an object.\");\n }\n const degree = value.degreeOfLinearPolarization;\n const angle = value.angleDegrees;\n if (\n typeof degree !== \"number\" ||\n !Number.isFinite(degree) ||\n degree < 0 ||\n degree > 1\n ) {\n throw new InvalidScientificInputError(\n path + \".degreeOfLinearPolarization must lie in [0, 1].\"\n );\n }\n if (typeof angle !== \"number\" || !Number.isFinite(angle)) {\n throw new InvalidScientificInputError(\n path + \".angleDegrees must be finite.\"\n );\n }\n return { degreeOfLinearPolarization: degree, angleDegrees: angle };\n}\n\nfunction stokesFromState(state: LinearPolarizationState): LinearStokes {\n const twice = (2 * state.angleDegrees * Math.PI) / 180;\n return {\n s0: 1,\n s1: state.degreeOfLinearPolarization * Math.cos(twice),\n s2: state.degreeOfLinearPolarization * Math.sin(twice)\n };\n}\n\nfunction stateFromStokes(stokes: LinearStokes): LinearPolarizationState {\n const polarized = Math.hypot(stokes.s1, stokes.s2);\n const degree = Math.min(1, polarized / stokes.s0);\n if (degree === 0) {\n return { ...UNPOLARIZED };\n }\n let angle = (Math.atan2(stokes.s2, stokes.s1) * 90) / Math.PI;\n if (angle < 0) angle += 180;\n return { degreeOfLinearPolarization: degree, angleDegrees: angle };\n}\n\n/**\n * Mueller matrix of a linear diattenuator (principal intensity transmittances k1 along the axis\n * and k2 across it, axis at theta) applied to a linear Stokes vector.\n */\nfunction applyLinearPolarizer(\n stokes: LinearStokes,\n k1: number,\n k2: number,\n axisDegrees: number\n): LinearStokes {\n const twice = (2 * axisDegrees * Math.PI) / 180;\n const c = Math.cos(twice);\n const sn = Math.sin(twice);\n const sum = (k1 + k2) / 2;\n const difference = (k1 - k2) / 2;\n const geometric = Math.sqrt(k1 * k2);\n return {\n s0: sum * stokes.s0 + difference * (c * stokes.s1 + sn * stokes.s2),\n s1:\n difference * c * stokes.s0 +\n (sum * c * c + geometric * sn * sn) * stokes.s1 +\n (sum - geometric) * c * sn * stokes.s2,\n s2:\n difference * sn * stokes.s0 +\n (sum - geometric) * c * sn * stokes.s1 +\n (sum * sn * sn + geometric * c * c) * stokes.s2\n };\n}\n\ninterface ResolvedComponent {\n resolved: ResolvedFrontOfLensFilterTransmission;\n outgoing: LinearStokes;\n}\n\nfunction resolveComponent(\n input: ResolveFrontOfLensFilterTransmissionInput,\n incoming: LinearStokes\n): ResolvedComponent {\n const profile =\n parseFrontOfLensFilterProfile(\n input.profile\n );\n const wavelength =\n scientificWavelength(\n input.wavelengthNanometers\n );\n\n if (\n input.wavelengthBasis !==\n profile.wavelengthBasis\n ) {\n throw new InvalidScientificInputError(\n \"Filter and requested wavelength bases must match; implicit air/vacuum conversion is not performed.\"\n );\n }\n if (\n wavelength <\n profile\n .wavelengthRangeNanometers\n .minimum ||\n wavelength >\n profile\n .wavelengthRangeNanometers\n .maximum\n ) {\n throw new InvalidScientificInputError(\n \"Requested wavelength lies outside the filter applicability range.\"\n );\n }\n\n let factor: number;\n let outgoing: LinearStokes;\n const transmission =\n profile.transmission;\n\n if (\n transmission.kind ===\n \"linear-polarizer\"\n ) {\n const k1 = transmission.principalTransmittance.value;\n const k2 = k1 / transmission.extinctionRatio.value;\n outgoing = applyLinearPolarizer(\n incoming,\n k1,\n k2,\n transmission.transmissionAxisDegrees\n );\n factor = outgoing.s0 / incoming.s0;\n } else {\n if (\n transmission.kind ===\n \"neutral-linear-transmission\"\n ) {\n factor =\n transmission\n .linearTransmissionFactor\n .value;\n } else if (\n transmission.kind ===\n \"neutral-optical-density\"\n ) {\n factor =\n Math.pow(\n 10,\n -transmission\n .opticalDensityBase10\n .value\n );\n } else {\n factor =\n interpolateSpectralTransmission(\n transmission.samples.value,\n wavelength\n );\n }\n outgoing = {\n s0: incoming.s0 * factor,\n s1: incoming.s1 * factor,\n s2: incoming.s2 * factor\n };\n }\n\n if (\n !Number.isFinite(factor) ||\n factor <= 0 ||\n factor > 1\n ) {\n throw new InvalidScientificInputError(\n \"Resolved passive filter transmission must remain finite and in (0, 1].\"\n );\n }\n\n const attenuationStops =\n -Math.log2(factor);\n const opticalDensityBase10 =\n -Math.log10(factor);\n\n if (\n !Number.isFinite(\n attenuationStops\n ) ||\n !Number.isFinite(\n opticalDensityBase10\n )\n ) {\n throw new InvalidScientificInputError(\n \"Resolved filter attenuation diagnostics must remain finite.\"\n );\n }\n\n const polarizer = transmission.kind === \"linear-polarizer\";\n return {\n outgoing,\n resolved: {\n schemaVersion:\n profile.schemaVersion,\n filterId:\n profile.filterId,\n profileVersion:\n profile.profileVersion,\n identityScope:\n \"photivra-generic-unbranded\",\n position:\n \"front-of-lens\",\n scientificStatus:\n profile.scientificStatus,\n wavelengthNanometers:\n wavelength,\n wavelengthBasis:\n input.wavelengthBasis,\n transmissionKind:\n transmission.kind,\n linearTransmissionFactor:\n factor,\n attenuationStops,\n opticalDensityBase10,\n polarizationModeled:\n polarizer,\n incidentPolarization:\n stateFromStokes(incoming),\n transmittedPolarization:\n stateFromStokes(outgoing),\n wavelengthChangingBehaviorModeled:\n false,\n lensTransmissionIncluded:\n false,\n sensorOpticalStackIncluded:\n false,\n fieldThroughputIncluded:\n false,\n uncertainty:\n profile.uncertainty,\n evidence: [\n ...profile.evidence,\n ...transmissionEvidence(\n transmission\n )\n ],\n limitations: [\n ...profile.limitations,\n \"Front-of-lens transmission is independent of lens aperture geometry, focus/DOF, diffraction and sensor optical-stack response.\",\n polarizer\n ? \"Linear diattenuator on linear Stokes parameters; circular polarization, retardance, angle-of-incidence dependence and inter-filter reflections/flare/ghosting are not modeled.\"\n : \"Polarization and inter-filter reflections/flare/ghosting are not modeled.\"\n ]\n }\n };\n}\n\n/**\n * Resolves one passive filter at one wavelength. Non-polarizing filters scale all Stokes\n * components equally, so their transmission does not depend on the incident polarization.\n */\nexport function resolveFrontOfLensFilterTransmission(\n input:\n ResolveFrontOfLensFilterTransmissionInput\n): ResolvedFrontOfLensFilterTransmission {\n requireInputKeys(input, \"resolveFrontOfLensFilterTransmission\", [\"profile\", \"wavelengthNanometers\", \"wavelengthBasis\", \"incidentPolarization\"]);\n return resolveComponent(\n input,\n stokesFromState(\n parsePolarizationState(\n input.incidentPolarization,\n \"incidentPolarization\"\n )\n )\n ).resolved;\n}\n\n/**\n * Combines several passive front-of-lens filters at one wavelength, in light-path order, and keeps\n * each filter's identity. Without a polarizer the result is the product of the transmissions. With\n * one, linear Stokes parameters pass through the Mueller matrices in order.\n */\nexport function composeFrontOfLensFilterTransmission(\n input:\n ComposeFrontOfLensFilterTransmissionInput\n): ComposedFrontOfLensFilterTransmission {\n requireInputKeys(input, \"composeFrontOfLensFilterTransmission\", [\"filters\", \"wavelengthNanometers\", \"wavelengthBasis\", \"incidentPolarization\"]);\n if (\n !Array.isArray(\n input.filters\n ) ||\n input.filters.length === 0\n ) {\n throw new InvalidConfigurationError(\n \"filters must be a non-empty array.\"\n );\n }\n\n const incidentPolarization = parsePolarizationState(\n input.incidentPolarization,\n \"incidentPolarization\"\n );\n const incident = stokesFromState(incidentPolarization);\n let stokes = incident;\n const components: ResolvedFrontOfLensFilterTransmission[] = [];\n for (const profile of input.filters) {\n const component = resolveComponent(\n {\n profile,\n wavelengthNanometers:\n input.wavelengthNanometers,\n wavelengthBasis:\n input.wavelengthBasis\n },\n stokes\n );\n components.push(component.resolved);\n stokes = component.outgoing;\n }\n\n const combined = stokes.s0 / incident.s0;\n if (\n !Number.isFinite(combined) ||\n combined <= 0 ||\n combined > 1\n ) {\n throw new InvalidScientificInputError(\n \"Combined passive filter transmission must remain finite and in (0, 1].\"\n );\n }\n\n const stops =\n -Math.log2(combined);\n if (!Number.isFinite(stops)) {\n throw new InvalidScientificInputError(\n \"Combined filter attenuation must remain finite.\"\n );\n }\n\n const polarizationModeled = components.some(\n (component) => component.polarizationModeled\n );\n return {\n schemaVersion: polarizationModeled\n ? FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION\n : FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION,\n wavelengthNanometers:\n scientificWavelength(\n input.wavelengthNanometers\n ),\n wavelengthBasis:\n input.wavelengthBasis,\n appliedFilterCount:\n components.length,\n components,\n combinedLinearTransmissionFactor:\n combined,\n combinedAttenuationStops:\n stops,\n scientificStatus:\n components.some(\n (component) =>\n component\n .scientificStatus ===\n \"approximation\"\n )\n ? \"approximation\"\n : \"calibrated\",\n uncertaintyPropagation:\n \"not-propagated\",\n uncertaintyLimitation:\n \"Component filter uncertainties are preserved individually; aggregate numeric uncertainty is not propagated because independence/correlation is not assumed.\",\n compositionModel: polarizationModeled\n ? \"ordered-linear-stokes-mueller-no-inter-filter-reflections\"\n : \"independent-multiplicative-unpolarized-transmission-no-inter-filter-reflections\",\n polarizationModeled,\n incidentPolarization,\n transmittedPolarization:\n stateFromStokes(stokes),\n wavelengthChangingBehaviorModeled:\n false,\n lensTransmissionIncluded:\n false,\n sensorOpticalStackIncluded:\n false,\n fieldThroughputIncluded:\n false\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"front-of-lens-filter.js","sourceRoot":"","sources":["../../src/optics/front-of-lens-filter.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Generic filters that screw onto the front of the lens.\n *\n * Schema 0.1.0 is explicitly unbranded and unpolarized. It models only passive transmission in front\n * of the lens. It does not cover reflections between stacked filters, flare or ghosting, or filters\n * that change wavelength.\n *\n * Schema 0.2.0 adds one polarizing kind: a linear (partial) polarizer. It has a principal\n * transmittance k1, an extinction ratio k1/k2 and a transmission-axis angle. Polarization is carried\n * as linear Stokes parameters (S0, S1, S2). Filters are applied in order using the Mueller matrix of\n * a linear diattenuator (Gil, arXiv:2002.04105, eqs. 134-135, free; Malus's law: OpenStax University\n * Physics Vol. 3, sec. 1.7, free. Also see: Chipman, Handbook of Optics vol. I ch. 22, 3rd ed., 2010;\n * Goldstein, Polarized Light, 3rd ed., ch. 4-5; Born & Wolf, Principles of Optics, sec. 1.4.2):\n * T = (k1 + k2)/2 + (k1 - k2)/2 * P * cos(2 (psi - theta))\n * Here P is the incident light's degree of linear polarization, psi its polarization angle and theta\n * the filter axis angle.\n * - For P = 1 this is Malus's law: k1 cos^2(psi - theta) + k2 sin^2(psi - theta).\n * - For unpolarized light it is (k1 + k2)/2, about half of k1.\n * Not modelled: circular polarization, retardance (for example the quarter-wave plate in a circular\n * polarizer), dependence on the angle of incidence, and depolarization.\n * @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceBackedFact,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport {\n parseSpectralWavelengthBasis,\n type SpectralWavelengthBasis\n} from \"../core/spectral.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport { requireInputKeys, rejectUnknownVariantFields, UNCERTAINTY_VARIANT_FIELDS, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, requireConfigFinite as requireFinite, parseConfigScientificStatus as parseScientificStatus, parseConfigLimitations as parseLimitations, requireConfigFiniteAboveZero as requirePositiveFinite, requireConfigFiniteAtLeastZero as requireNonNegativeFinite } from \"../core/record-validation.js\";\n\nexport const FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION =\n \"0.1.0\" as const;\n/** Schema that also allows the `linear-polarizer` transmission kind. */\nexport const FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION =\n \"0.2.0\" as const;\n\nexport type FrontOfLensFilterProfileSchemaVersion =\n | typeof FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION\n | typeof FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION;\n\n/** Partially linearly polarized light: degree P in [0, 1] and polarization angle psi. */\nexport interface LinearPolarizationState {\n /** Degree of linear polarization P in [0, 1]; 0 is unpolarized. */\n degreeOfLinearPolarization: number;\n /** Electric-field polarization angle, degrees counter-clockwise from image +X. */\n angleDegrees: number;\n}\n\nexport type FrontOfLensFilterScientificStatus =\n | \"calibrated\"\n | \"approximation\";\n\nexport type FrontOfLensFilterUncertainty =\n | {\n kind: \"relative\";\n fraction: number;\n basis: string;\n }\n | {\n kind: \"not-quantified\";\n limitation: string;\n };\n\nexport interface FrontOfLensFilterSpectralSample {\n wavelengthNanometers: number;\n linearTransmissionFactor: number;\n}\n\nexport type FrontOfLensFilterTransmissionModel =\n | {\n kind: \"neutral-linear-transmission\";\n linearTransmissionFactor:\n EvidenceBackedFact<number>;\n }\n | {\n kind: \"neutral-optical-density\";\n opticalDensityBase10:\n EvidenceBackedFact<number>;\n }\n | {\n kind: \"spectral-transmission\";\n samples:\n EvidenceBackedFact<\n readonly FrontOfLensFilterSpectralSample[]\n >;\n }\n | {\n /** Schema 0.2.0 only. Neutral (wavelength-independent) within the declared range. */\n kind: \"linear-polarizer\";\n /** k1: intensity transmittance for light polarized along the transmission axis, (0, 1]. */\n principalTransmittance:\n EvidenceBackedFact<number>;\n /** k1 / k2. Finite and >= 1. Use a large finite ratio for a near-ideal polarizer. */\n extinctionRatio:\n EvidenceBackedFact<number>;\n /** Transmission-axis angle as mounted, degrees counter-clockwise from image +X. */\n transmissionAxisDegrees: number;\n };\n\nexport interface FrontOfLensFilterProfile {\n schemaVersion:\n FrontOfLensFilterProfileSchemaVersion;\n filterId: string;\n profileVersion: string;\n identityScope:\n \"photivra-generic-unbranded\";\n position: \"front-of-lens\";\n scientificStatus:\n FrontOfLensFilterScientificStatus;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n wavelengthRangeNanometers: {\n minimum: number;\n maximum: number;\n };\n transmission:\n FrontOfLensFilterTransmissionModel;\n uncertainty:\n FrontOfLensFilterUncertainty;\n /** True exactly when the transmission kind is `linear-polarizer` (schema 0.2.0). */\n polarizationModeled: boolean;\n wavelengthChangingBehaviorModeled:\n false;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface ResolveFrontOfLensFilterTransmissionInput {\n profile: FrontOfLensFilterProfile;\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n /** Incident polarization; omitted means unpolarized. */\n incidentPolarization?: LinearPolarizationState;\n}\n\nexport interface ResolvedFrontOfLensFilterTransmission {\n schemaVersion:\n FrontOfLensFilterProfileSchemaVersion;\n filterId: string;\n profileVersion: string;\n identityScope:\n \"photivra-generic-unbranded\";\n position: \"front-of-lens\";\n scientificStatus:\n FrontOfLensFilterScientificStatus;\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n transmissionKind:\n FrontOfLensFilterTransmissionModel[\"kind\"];\n /** Intensity transmittance for the declared incident polarization. */\n linearTransmissionFactor: number;\n attenuationStops: number;\n opticalDensityBase10: number;\n polarizationModeled: boolean;\n incidentPolarization: LinearPolarizationState;\n transmittedPolarization: LinearPolarizationState;\n wavelengthChangingBehaviorModeled:\n false;\n lensTransmissionIncluded: false;\n sensorOpticalStackIncluded: false;\n fieldThroughputIncluded: false;\n uncertainty:\n FrontOfLensFilterUncertainty;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface ComposeFrontOfLensFilterTransmissionInput {\n /** Filters in light-path order (scene side first). */\n filters:\n readonly FrontOfLensFilterProfile[];\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n /** Incident scene polarization; omitted means unpolarized. */\n incidentPolarization?: LinearPolarizationState;\n}\n\nexport interface ComposedFrontOfLensFilterTransmission {\n schemaVersion:\n FrontOfLensFilterProfileSchemaVersion;\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n appliedFilterCount: number;\n components:\n readonly ResolvedFrontOfLensFilterTransmission[];\n combinedLinearTransmissionFactor:\n number;\n combinedAttenuationStops: number;\n scientificStatus:\n FrontOfLensFilterScientificStatus;\n uncertaintyPropagation:\n \"not-propagated\";\n uncertaintyLimitation: string;\n compositionModel:\n | \"independent-multiplicative-unpolarized-transmission-no-inter-filter-reflections\"\n | \"ordered-linear-stokes-mueller-no-inter-filter-reflections\";\n polarizationModeled: boolean;\n incidentPolarization: LinearPolarizationState;\n transmittedPolarization: LinearPolarizationState;\n wavelengthChangingBehaviorModeled:\n false;\n lensTransmissionIncluded: false;\n sensorOpticalStackIncluded: false;\n fieldThroughputIncluded: false;\n}\n\nfunction requirePassiveTransmission(\n value: unknown,\n path: string\n): number {\n const parsed = requirePositiveFinite(\n value,\n path\n );\n if (parsed > 1) {\n throw new InvalidConfigurationError(\n path +\n \" must be less than or equal to one for a passive filter.\"\n );\n }\n return parsed;\n}\n\nexport function parseRange(\n value: unknown,\n path: string\n): {\n minimum: number;\n maximum: number;\n} {\n const record = requireRecord(\n value,\n path, [\"minimum\", \"maximum\"]\n );\n const minimum =\n requirePositiveFinite(\n record.minimum,\n path + \".minimum\"\n );\n const maximum =\n requirePositiveFinite(\n record.maximum,\n path + \".maximum\"\n );\n if (minimum > maximum) {\n throw new InvalidConfigurationError(\n path +\n \".minimum must be less than or equal to maximum.\"\n );\n }\n return {\n minimum,\n maximum\n };\n}\n\nexport function parseResolvedBasis(\n value: unknown,\n path: string\n): Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n> {\n const parsed =\n parseSpectralWavelengthBasis(\n value,\n path\n );\n if (parsed === \"unspecified\") {\n throw new InvalidConfigurationError(\n path +\n ' must resolve to \"air\" or \"vacuum\".'\n );\n }\n return parsed;\n}\n\nfunction parseUncertainty(\n value: unknown,\n path: string\n): FrontOfLensFilterUncertainty {\n const record = requireRecord(\n value,\n path, null\n );\n rejectUnknownVariantFields(record, \"kind\", UNCERTAINTY_VARIANT_FIELDS, path);\n\n if (record.kind === \"relative\") {\n const fraction =\n requireNonNegativeFinite(\n record.fraction,\n path + \".fraction\"\n );\n if (fraction > 1) {\n throw new InvalidConfigurationError(\n path +\n \".fraction must be less than or equal to one.\"\n );\n }\n return {\n kind: \"relative\",\n fraction,\n basis:\n requireNonEmptyString(\n record.basis,\n path + \".basis\"\n )\n };\n }\n\n if (\n record.kind ===\n \"not-quantified\"\n ) {\n return {\n kind: \"not-quantified\",\n limitation:\n requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseReusableNumericEvidence(\n value: unknown,\n path: string\n): readonly EvidenceProvenance[] {\n const evidence =\n parseEvidenceList(\n value,\n path\n );\n if (\n evidence.some(\n (entry) =>\n entry.reuseStatus ===\n \"factual-reference-only\"\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \" for embedded numeric filter data must be reusable-data or photivra-owned.\"\n );\n }\n return evidence;\n}\n\nfunction parseSpectralSamples(\n value: unknown,\n path: string\n): readonly FrontOfLensFilterSpectralSample[] {\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(\n (entry, index) => {\n const samplePath =\n path +\n \"[\" +\n index +\n \"]\";\n const record =\n requireRecord(\n entry,\n samplePath, [\"wavelengthNanometers\", \"linearTransmissionFactor\"]\n );\n const wavelengthNanometers =\n requirePositiveFinite(\n record.wavelengthNanometers,\n samplePath +\n \".wavelengthNanometers\"\n );\n if (\n wavelengthNanometers <=\n previous\n ) {\n throw new InvalidConfigurationError(\n path +\n \" wavelengths must be strictly increasing.\"\n );\n }\n previous =\n wavelengthNanometers;\n return {\n wavelengthNanometers,\n linearTransmissionFactor:\n requirePassiveTransmission(\n record.linearTransmissionFactor,\n samplePath +\n \".linearTransmissionFactor\"\n )\n };\n }\n );\n}\n\nfunction parseTransmission(\n value: unknown,\n path: string,\n polarizerAllowed: boolean\n): FrontOfLensFilterTransmissionModel {\n const record = requireRecord(\n value,\n path, null\n );\n rejectUnknownVariantFields(record, \"kind\", {\n \"neutral-linear-transmission\": [\"kind\", \"linearTransmissionFactor\"],\n \"neutral-optical-density\": [\"kind\", \"opticalDensityBase10\"],\n \"spectral-transmission\": [\"kind\", \"samples\"],\n \"linear-polarizer\": [\"kind\", \"principalTransmittance\", \"extinctionRatio\", \"transmissionAxisDegrees\"]\n }, path);\n\n if (record.kind === \"linear-polarizer\") {\n if (!polarizerAllowed) {\n throw new InvalidConfigurationError(\n path + '.kind \"linear-polarizer\" requires schemaVersion \"' +\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION + '\".'\n );\n }\n const principal = requireRecord(\n record.principalTransmittance,\n path + \".principalTransmittance\", [\"value\", \"evidence\"]\n );\n const extinction = requireRecord(\n record.extinctionRatio,\n path + \".extinctionRatio\", [\"value\", \"evidence\"]\n );\n const ratio = requireFinite(\n extinction.value,\n path + \".extinctionRatio.value\"\n );\n if (ratio < 1) {\n throw new InvalidConfigurationError(\n path + \".extinctionRatio.value must be at least one.\"\n );\n }\n return {\n kind: \"linear-polarizer\",\n principalTransmittance: {\n value: requirePassiveTransmission(\n principal.value,\n path + \".principalTransmittance.value\"\n ),\n evidence: parseEvidenceList(\n principal.evidence,\n path + \".principalTransmittance.evidence\"\n )\n },\n extinctionRatio: {\n value: ratio,\n evidence: parseEvidenceList(\n extinction.evidence,\n path + \".extinctionRatio.evidence\"\n )\n },\n transmissionAxisDegrees: requireFinite(\n record.transmissionAxisDegrees,\n path + \".transmissionAxisDegrees\"\n )\n };\n }\n\n if (\n record.kind ===\n \"neutral-linear-transmission\"\n ) {\n const fact = requireRecord(\n record.linearTransmissionFactor,\n path +\n \".linearTransmissionFactor\", [\"value\", \"evidence\"]\n );\n return {\n kind:\n \"neutral-linear-transmission\",\n linearTransmissionFactor: {\n value:\n requirePassiveTransmission(\n fact.value,\n path +\n \".linearTransmissionFactor.value\"\n ),\n evidence:\n parseEvidenceList(\n fact.evidence,\n path +\n \".linearTransmissionFactor.evidence\"\n )\n }\n };\n }\n\n if (\n record.kind ===\n \"neutral-optical-density\"\n ) {\n const fact = requireRecord(\n record.opticalDensityBase10,\n path +\n \".opticalDensityBase10\", [\"value\", \"evidence\"]\n );\n return {\n kind:\n \"neutral-optical-density\",\n opticalDensityBase10: {\n value:\n requireNonNegativeFinite(\n fact.value,\n path +\n \".opticalDensityBase10.value\"\n ),\n evidence:\n parseEvidenceList(\n fact.evidence,\n path +\n \".opticalDensityBase10.evidence\"\n )\n }\n };\n }\n\n if (\n record.kind ===\n \"spectral-transmission\"\n ) {\n const fact = requireRecord(\n record.samples,\n path + \".samples\", [\"value\", \"evidence\"]\n );\n return {\n kind:\n \"spectral-transmission\",\n samples: {\n value:\n parseSpectralSamples(\n fact.value,\n path +\n \".samples.value\"\n ),\n evidence:\n parseReusableNumericEvidence(\n fact.evidence,\n path +\n \".samples.evidence\"\n )\n }\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\n/**\n * Parses one generic front-of-lens transmission filter.\n *\n * Schema 0.1.0 is explicitly unbranded and unpolarized. It models only\n * passive transmission in front of the lens. It does not cover reflections\n * between stacked filters, polarization, flare or ghosting, or filters that\n * change wavelength.\n */\nexport function parseFrontOfLensFilterProfile(\n value: unknown\n): FrontOfLensFilterProfile {\n const record = requireRecord(\n value,\n \"frontOfLensFilterProfile\", [\"schemaVersion\", \"identityScope\", \"position\", \"wavelengthChangingBehaviorModeled\", \"polarizationModeled\", \"scientificStatus\", \"uncertainty\", \"wavelengthRangeNanometers\", \"transmission\", \"filterId\", \"profileVersion\", \"wavelengthBasis\", \"evidence\", \"limitations\"]\n );\n\n if (\n record.schemaVersion !==\n FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION &&\n record.schemaVersion !==\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'frontOfLensFilterProfile.schemaVersion must be \"' +\n FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION +\n '\" or \"' +\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n const schemaVersion =\n record.schemaVersion as FrontOfLensFilterProfileSchemaVersion;\n if (\n record.identityScope !==\n \"photivra-generic-unbranded\"\n ) {\n throw new InvalidConfigurationError(\n 'frontOfLensFilterProfile.identityScope must be \"photivra-generic-unbranded\".'\n );\n }\n if (\n record.position !==\n \"front-of-lens\"\n ) {\n throw new InvalidConfigurationError(\n 'frontOfLensFilterProfile.position must be \"front-of-lens\".'\n );\n }\n if (\n record.wavelengthChangingBehaviorModeled !==\n false ||\n (schemaVersion ===\n FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION &&\n record.polarizationModeled !== false)\n ) {\n throw new InvalidConfigurationError(\n \"frontOfLensFilterProfile must explicitly keep polarization and wavelength-changing behavior unmodeled in schema 0.1.0.\"\n );\n }\n\n const status =\n parseScientificStatus(\n record.scientificStatus,\n \"frontOfLensFilterProfile.scientificStatus\"\n );\n const uncertainty =\n parseUncertainty(\n record.uncertainty,\n \"frontOfLensFilterProfile.uncertainty\"\n );\n\n if (\n status === \"calibrated\" &&\n uncertainty.kind !==\n \"relative\"\n ) {\n throw new InvalidConfigurationError(\n \"A calibrated filter profile requires quantified relative uncertainty.\"\n );\n }\n\n const range =\n parseRange(\n record.wavelengthRangeNanometers,\n \"frontOfLensFilterProfile.wavelengthRangeNanometers\"\n );\n const transmission =\n parseTransmission(\n record.transmission,\n \"frontOfLensFilterProfile.transmission\",\n schemaVersion ===\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION\n );\n const polarizationModeled =\n transmission.kind === \"linear-polarizer\";\n if (record.polarizationModeled !== polarizationModeled) {\n throw new InvalidConfigurationError(\n \"frontOfLensFilterProfile.polarizationModeled must be true exactly for a linear-polarizer transmission.\"\n );\n }\n\n if (\n transmission.kind ===\n \"spectral-transmission\"\n ) {\n const samples =\n transmission.samples.value;\n if (\n samples[0]!\n .wavelengthNanometers >\n range.minimum ||\n samples[\n samples.length - 1\n ]!.wavelengthNanometers <\n range.maximum\n ) {\n throw new InvalidConfigurationError(\n \"Spectral filter samples must cover the declared wavelength range.\"\n );\n }\n }\n\n return {\n schemaVersion,\n filterId:\n requireNonEmptyString(\n record.filterId,\n \"frontOfLensFilterProfile.filterId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"frontOfLensFilterProfile.profileVersion\"\n ),\n identityScope:\n \"photivra-generic-unbranded\",\n position:\n \"front-of-lens\",\n scientificStatus:\n status,\n wavelengthBasis:\n parseResolvedBasis(\n record.wavelengthBasis,\n \"frontOfLensFilterProfile.wavelengthBasis\"\n ),\n wavelengthRangeNanometers:\n range,\n transmission,\n uncertainty,\n polarizationModeled,\n wavelengthChangingBehaviorModeled:\n false,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"frontOfLensFilterProfile.evidence\"\n ),\n limitations:\n parseLimitations(\n record.limitations,\n \"frontOfLensFilterProfile.limitations\"\n )\n };\n}\n\nfunction interpolateSpectralTransmission(\n samples:\n readonly FrontOfLensFilterSpectralSample[],\n wavelengthNanometers: number\n): number {\n const first =\n samples[0]!;\n const last =\n samples[\n samples.length - 1\n ]!;\n\n if (\n wavelengthNanometers ===\n first.wavelengthNanometers\n ) {\n return first\n .linearTransmissionFactor;\n }\n\n for (\n let index = 1;\n index < samples.length;\n index += 1\n ) {\n const right =\n samples[index]!;\n if (\n wavelengthNanometers <=\n right.wavelengthNanometers\n ) {\n const left =\n samples[\n index - 1\n ]!;\n if (\n wavelengthNanometers ===\n right.wavelengthNanometers\n ) {\n return right\n .linearTransmissionFactor;\n }\n const phase =\n (wavelengthNanometers -\n left.wavelengthNanometers) /\n (right.wavelengthNanometers -\n left.wavelengthNanometers);\n return (\n left\n .linearTransmissionFactor +\n phase *\n (right\n .linearTransmissionFactor -\n left\n .linearTransmissionFactor)\n );\n }\n }\n\n return last\n .linearTransmissionFactor;\n}\n\nfunction scientificWavelength(\n value: number\n): number {\n if (\n !Number.isFinite(value) ||\n value <= 0\n ) {\n throw new InvalidScientificInputError(\n \"wavelengthNanometers must be finite and greater than zero.\"\n );\n }\n return value;\n}\n\nfunction transmissionEvidence(\n transmission:\n FrontOfLensFilterTransmissionModel\n): readonly EvidenceProvenance[] {\n if (\n transmission.kind ===\n \"neutral-linear-transmission\"\n ) {\n return transmission\n .linearTransmissionFactor\n .evidence;\n }\n if (\n transmission.kind ===\n \"neutral-optical-density\"\n ) {\n return transmission\n .opticalDensityBase10\n .evidence;\n }\n if (transmission.kind === \"linear-polarizer\") {\n return [\n ...transmission.principalTransmittance.evidence,\n ...transmission.extinctionRatio.evidence\n ];\n }\n return transmission\n .samples.evidence;\n}\n\n/** Linear Stokes vector (S0, S1, S2); circular S3 is not modeled. */\ninterface LinearStokes {\n s0: number;\n s1: number;\n s2: number;\n}\n\nconst UNPOLARIZED: LinearPolarizationState = /* @__PURE__ */ Object.freeze({\n degreeOfLinearPolarization: 0,\n angleDegrees: 0\n});\n\nfunction parsePolarizationState(\n value: LinearPolarizationState | undefined,\n path: string\n): LinearPolarizationState {\n if (value === undefined) {\n return { ...UNPOLARIZED };\n }\n if (typeof value !== \"object\" || value === null) {\n throw new InvalidConfigurationError(path + \" must be an object.\");\n }\n const degree = value.degreeOfLinearPolarization;\n const angle = value.angleDegrees;\n if (\n typeof degree !== \"number\" ||\n !Number.isFinite(degree) ||\n degree < 0 ||\n degree > 1\n ) {\n throw new InvalidScientificInputError(\n path + \".degreeOfLinearPolarization must lie in [0, 1].\"\n );\n }\n if (typeof angle !== \"number\" || !Number.isFinite(angle)) {\n throw new InvalidScientificInputError(\n path + \".angleDegrees must be finite.\"\n );\n }\n return { degreeOfLinearPolarization: degree, angleDegrees: angle };\n}\n\nfunction stokesFromState(state: LinearPolarizationState): LinearStokes {\n const twice = (2 * state.angleDegrees * Math.PI) / 180;\n return {\n s0: 1,\n s1: state.degreeOfLinearPolarization * Math.cos(twice),\n s2: state.degreeOfLinearPolarization * Math.sin(twice)\n };\n}\n\nfunction stateFromStokes(stokes: LinearStokes): LinearPolarizationState {\n const polarized = Math.hypot(stokes.s1, stokes.s2);\n const degree = Math.min(1, polarized / stokes.s0);\n if (degree === 0) {\n return { ...UNPOLARIZED };\n }\n let angle = (Math.atan2(stokes.s2, stokes.s1) * 90) / Math.PI;\n if (angle < 0) angle += 180;\n return { degreeOfLinearPolarization: degree, angleDegrees: angle };\n}\n\n/**\n * Mueller matrix of a linear diattenuator (principal intensity transmittances k1 along the axis\n * and k2 across it, axis at theta) applied to a linear Stokes vector.\n */\nfunction applyLinearPolarizer(\n stokes: LinearStokes,\n k1: number,\n k2: number,\n axisDegrees: number\n): LinearStokes {\n const twice = (2 * axisDegrees * Math.PI) / 180;\n const c = Math.cos(twice);\n const sn = Math.sin(twice);\n const sum = (k1 + k2) / 2;\n const difference = (k1 - k2) / 2;\n const geometric = Math.sqrt(k1 * k2);\n return {\n s0: sum * stokes.s0 + difference * (c * stokes.s1 + sn * stokes.s2),\n s1:\n difference * c * stokes.s0 +\n (sum * c * c + geometric * sn * sn) * stokes.s1 +\n (sum - geometric) * c * sn * stokes.s2,\n s2:\n difference * sn * stokes.s0 +\n (sum - geometric) * c * sn * stokes.s1 +\n (sum * sn * sn + geometric * c * c) * stokes.s2\n };\n}\n\ninterface ResolvedComponent {\n resolved: ResolvedFrontOfLensFilterTransmission;\n outgoing: LinearStokes;\n}\n\nfunction resolveComponent(\n input: ResolveFrontOfLensFilterTransmissionInput,\n incoming: LinearStokes\n): ResolvedComponent {\n const profile =\n parseFrontOfLensFilterProfile(\n input.profile\n );\n const wavelength =\n scientificWavelength(\n input.wavelengthNanometers\n );\n\n if (\n input.wavelengthBasis !==\n profile.wavelengthBasis\n ) {\n throw new InvalidScientificInputError(\n \"Filter and requested wavelength bases must match; implicit air/vacuum conversion is not performed.\"\n );\n }\n if (\n wavelength <\n profile\n .wavelengthRangeNanometers\n .minimum ||\n wavelength >\n profile\n .wavelengthRangeNanometers\n .maximum\n ) {\n throw new InvalidScientificInputError(\n \"Requested wavelength lies outside the filter applicability range.\"\n );\n }\n\n let factor: number;\n let outgoing: LinearStokes;\n const transmission =\n profile.transmission;\n\n if (\n transmission.kind ===\n \"linear-polarizer\"\n ) {\n const k1 = transmission.principalTransmittance.value;\n const k2 = k1 / transmission.extinctionRatio.value;\n outgoing = applyLinearPolarizer(\n incoming,\n k1,\n k2,\n transmission.transmissionAxisDegrees\n );\n factor = outgoing.s0 / incoming.s0;\n } else {\n if (\n transmission.kind ===\n \"neutral-linear-transmission\"\n ) {\n factor =\n transmission\n .linearTransmissionFactor\n .value;\n } else if (\n transmission.kind ===\n \"neutral-optical-density\"\n ) {\n factor =\n Math.pow(\n 10,\n -transmission\n .opticalDensityBase10\n .value\n );\n } else {\n factor =\n interpolateSpectralTransmission(\n transmission.samples.value,\n wavelength\n );\n }\n outgoing = {\n s0: incoming.s0 * factor,\n s1: incoming.s1 * factor,\n s2: incoming.s2 * factor\n };\n }\n\n if (\n !Number.isFinite(factor) ||\n factor <= 0 ||\n factor > 1\n ) {\n throw new InvalidScientificInputError(\n \"Resolved passive filter transmission must remain finite and in (0, 1].\"\n );\n }\n\n const attenuationStops =\n -Math.log2(factor);\n const opticalDensityBase10 =\n -Math.log10(factor);\n\n if (\n !Number.isFinite(\n attenuationStops\n ) ||\n !Number.isFinite(\n opticalDensityBase10\n )\n ) {\n throw new InvalidScientificInputError(\n \"Resolved filter attenuation diagnostics must remain finite.\"\n );\n }\n\n const polarizer = transmission.kind === \"linear-polarizer\";\n return {\n outgoing,\n resolved: {\n schemaVersion:\n profile.schemaVersion,\n filterId:\n profile.filterId,\n profileVersion:\n profile.profileVersion,\n identityScope:\n \"photivra-generic-unbranded\",\n position:\n \"front-of-lens\",\n scientificStatus:\n profile.scientificStatus,\n wavelengthNanometers:\n wavelength,\n wavelengthBasis:\n input.wavelengthBasis,\n transmissionKind:\n transmission.kind,\n linearTransmissionFactor:\n factor,\n attenuationStops,\n opticalDensityBase10,\n polarizationModeled:\n polarizer,\n incidentPolarization:\n stateFromStokes(incoming),\n transmittedPolarization:\n stateFromStokes(outgoing),\n wavelengthChangingBehaviorModeled:\n false,\n lensTransmissionIncluded:\n false,\n sensorOpticalStackIncluded:\n false,\n fieldThroughputIncluded:\n false,\n uncertainty:\n profile.uncertainty,\n evidence: [\n ...profile.evidence,\n ...transmissionEvidence(\n transmission\n )\n ],\n limitations: [\n ...profile.limitations,\n \"Front-of-lens transmission is independent of lens aperture geometry, focus/DOF, diffraction and sensor optical-stack response.\",\n polarizer\n ? \"Linear diattenuator on linear Stokes parameters; circular polarization, retardance, angle-of-incidence dependence and inter-filter reflections/flare/ghosting are not modeled.\"\n : \"Polarization and inter-filter reflections/flare/ghosting are not modeled.\"\n ]\n }\n };\n}\n\n/**\n * Resolves one passive filter at one wavelength. Non-polarizing filters scale all Stokes\n * components equally, so their transmission does not depend on the incident polarization.\n */\nexport function resolveFrontOfLensFilterTransmission(\n input:\n ResolveFrontOfLensFilterTransmissionInput\n): ResolvedFrontOfLensFilterTransmission {\n requireInputKeys(input, \"resolveFrontOfLensFilterTransmission\", [\"profile\", \"wavelengthNanometers\", \"wavelengthBasis\", \"incidentPolarization\"]);\n return resolveComponent(\n input,\n stokesFromState(\n parsePolarizationState(\n input.incidentPolarization,\n \"incidentPolarization\"\n )\n )\n ).resolved;\n}\n\n/**\n * Combines several passive front-of-lens filters at one wavelength, in light-path order, and keeps\n * each filter's identity. Without a polarizer the result is the product of the transmissions. With\n * one, linear Stokes parameters pass through the Mueller matrices in order.\n */\nexport function composeFrontOfLensFilterTransmission(\n input:\n ComposeFrontOfLensFilterTransmissionInput\n): ComposedFrontOfLensFilterTransmission {\n requireInputKeys(input, \"composeFrontOfLensFilterTransmission\", [\"filters\", \"wavelengthNanometers\", \"wavelengthBasis\", \"incidentPolarization\"]);\n if (\n !Array.isArray(\n input.filters\n ) ||\n input.filters.length === 0\n ) {\n throw new InvalidConfigurationError(\n \"filters must be a non-empty array.\"\n );\n }\n\n const incidentPolarization = parsePolarizationState(\n input.incidentPolarization,\n \"incidentPolarization\"\n );\n const incident = stokesFromState(incidentPolarization);\n let stokes = incident;\n const components: ResolvedFrontOfLensFilterTransmission[] = [];\n for (const profile of input.filters) {\n const component = resolveComponent(\n {\n profile,\n wavelengthNanometers:\n input.wavelengthNanometers,\n wavelengthBasis:\n input.wavelengthBasis\n },\n stokes\n );\n components.push(component.resolved);\n stokes = component.outgoing;\n }\n\n const combined = stokes.s0 / incident.s0;\n if (\n !Number.isFinite(combined) ||\n combined <= 0 ||\n combined > 1\n ) {\n throw new InvalidScientificInputError(\n \"Combined passive filter transmission must remain finite and in (0, 1].\"\n );\n }\n\n const stops =\n -Math.log2(combined);\n if (!Number.isFinite(stops)) {\n throw new InvalidScientificInputError(\n \"Combined filter attenuation must remain finite.\"\n );\n }\n\n const polarizationModeled = components.some(\n (component) => component.polarizationModeled\n );\n return {\n schemaVersion: polarizationModeled\n ? FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION\n : FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION,\n wavelengthNanometers:\n scientificWavelength(\n input.wavelengthNanometers\n ),\n wavelengthBasis:\n input.wavelengthBasis,\n appliedFilterCount:\n components.length,\n components,\n combinedLinearTransmissionFactor:\n combined,\n combinedAttenuationStops:\n stops,\n scientificStatus:\n components.some(\n (component) =>\n component\n .scientificStatus ===\n \"approximation\"\n )\n ? \"approximation\"\n : \"calibrated\",\n uncertaintyPropagation:\n \"not-propagated\",\n uncertaintyLimitation:\n \"Component filter uncertainties are preserved individually; aggregate numeric uncertainty is not propagated because independence/correlation is not assumed.\",\n compositionModel: polarizationModeled\n ? \"ordered-linear-stokes-mueller-no-inter-filter-reflections\"\n : \"independent-multiplicative-unpolarized-transmission-no-inter-filter-reflections\",\n polarizationModeled,\n incidentPolarization,\n transmittedPolarization:\n stateFromStokes(stokes),\n wavelengthChangingBehaviorModeled:\n false,\n lensTransmissionIncluded:\n false,\n sensorOpticalStackIncluded:\n false,\n fieldThroughputIncluded:\n false\n };\n}\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { EvidenceProvenance } from "../core/evidence-provenance.js";
|
|
2
2
|
import { type ResolvedGenericLens } from "../equipment/generic-lens-catalogue.js";
|
|
3
3
|
import { type LensSampledPsfProfile } from "./lens-psf-profile.js";
|
|
4
|
+
import { type DefocusBokehSiteKernel } from "./defocus-bokeh-kernel.js";
|
|
4
5
|
/** Wavelength nodes of a catalogue PSF profile, nm (they span the facade's 380–780 nm quadrature). */
|
|
5
6
|
export declare const GENERIC_LENS_PSF_WAVELENGTHS_NM: readonly [380, 450, 550, 650, 780];
|
|
6
7
|
/** Largest kernel radius of the aberration PSF in sites (before any defocus disc is convolved in). */
|
|
@@ -25,10 +26,11 @@ export interface GenericLensPsfInput {
|
|
|
25
26
|
x: number;
|
|
26
27
|
y: number;
|
|
27
28
|
};
|
|
28
|
-
/** Optional site kernel (2R_d + 1)² to convolve into
|
|
29
|
+
/** Optional site kernel (2R_d + 1)² to convolve into each node, by its field point (mm, +Y up): the `lens.defocus` bokeh kernel. */
|
|
29
30
|
extraKernel?: {
|
|
30
|
-
weights: Float64Array;
|
|
31
31
|
radius: number;
|
|
32
|
+
clipped?: boolean;
|
|
33
|
+
at(fieldXmm: number, fieldYmm: number): Float64Array;
|
|
32
34
|
};
|
|
33
35
|
evidence: readonly EvidenceProvenance[];
|
|
34
36
|
}
|
|
@@ -66,3 +68,17 @@ export declare function genericLensPsfKernelRadius(input: {
|
|
|
66
68
|
* kernel on the site lattice. Engine-owned (parsed once). Deterministic: the same input gives the same profile.
|
|
67
69
|
*/
|
|
68
70
|
export declare function createGenericLensPsfProfile(input: GenericLensPsfInput): GenericLensPsf;
|
|
71
|
+
/**
|
|
72
|
+
* #567: the catalogue lens's own bokeh kernel for `lens.defocus` (#553's shaped kernel with `lens.character.bokeh`), as the
|
|
73
|
+
* PSF's field-dependent extra kernel. The defocus is referred to the lens's focus, the balanced one of its PSF (W020 = −W040):
|
|
74
|
+
* the ray map (σc/2 + bρ²)·P of the paraxial focus gains −(b/2)·P, so the kernel is #553's for the signed blur σc − b. Rows are
|
|
75
|
+
* flipped from #553's (+Y down) to the profile's (+Y up). With a cat's eye each field point (tangent x/f, y/f: the rectilinear
|
|
76
|
+
* chief ray, distortion neglected) has its own kernel, padded to the axis kernel's radius (clipping only narrows the blur). Each
|
|
77
|
+
* call builds its kernel (the profile calls it once per field and wavelength node: 125 small kernels). `catsEye` false leaves it out.
|
|
78
|
+
*/
|
|
79
|
+
export declare function genericLensBokehKernel(lens: ResolvedGenericLens, diameterSites: number, side: 1 | -1, pitch: number, catsEye: boolean): {
|
|
80
|
+
axis: DefocusBokehSiteKernel;
|
|
81
|
+
radius: number;
|
|
82
|
+
clipped: boolean;
|
|
83
|
+
at(fieldXmm: number, fieldYmm: number): Float64Array;
|
|
84
|
+
};
|
|
@@ -23,6 +23,7 @@ import { InvalidScientificInputError } from "../core/validation.js";
|
|
|
23
23
|
import { genericLensDispersion } from "../equipment/generic-lens-catalogue.js";
|
|
24
24
|
import { markEngineOwnedLensSampledPsfProfile } from "./lens-psf-profile.js";
|
|
25
25
|
import { convolveSiteKernels } from "./defocus-disc-kernel.js";
|
|
26
|
+
import { createDefocusBokehSiteKernel } from "./defocus-bokeh-kernel.js";
|
|
26
27
|
/** Wavelength nodes of a catalogue PSF profile, nm (they span the facade's 380–780 nm quadrature). */
|
|
27
28
|
export const GENERIC_LENS_PSF_WAVELENGTHS_NM = /* @__PURE__ */ Object.freeze([380, 450, 550, 650, 780]);
|
|
28
29
|
/** Largest kernel radius of the aberration PSF in sites (before any defocus disc is convolved in). */
|
|
@@ -313,7 +314,7 @@ export function createGenericLensPsfProfile(input) {
|
|
|
313
314
|
const base = quadrant.get(Math.abs(x) + ":" + Math.abs(y) + ":" + nm);
|
|
314
315
|
let kernel = mirror(crop(base), radius, x < 0, y < 0);
|
|
315
316
|
if (extra)
|
|
316
|
-
kernel = convolveSiteKernels(kernel, radius, extra.
|
|
317
|
+
kernel = convolveSiteKernels(kernel, radius, extra.at(x, y), extra.radius);
|
|
317
318
|
nodes.push({ nodeId: "pv-" + x.toFixed(6) + "-" + y.toFixed(6) + "-" + nm,
|
|
318
319
|
coordinate: { focalLengthMm: f, focusDiopters, apertureFNumber: N, fieldXmm: x, fieldYmm: y, wavelengthNm: nm, signedDefocusImagePlaneMicrometers: 0 },
|
|
319
320
|
kernel: { widthSamples: w, heightSamples: w, samplePitchMicrometersX: pitch, samplePitchMicrometersY: pitch, centerSampleX: kernelRadius, centerSampleY: kernelRadius,
|
|
@@ -323,7 +324,7 @@ export function createGenericLensPsfProfile(input) {
|
|
|
323
324
|
const profile = { schemaVersion: "0.1.0", profileId: "photivra-" + lens.lensId + ":psf", profileVersion: "1.0.0", scientificStatus: "approximation",
|
|
324
325
|
opticalDomain: "lens-primary-optical-path-only", coordinateSystem: "image-plane-metric", fieldAxes: "+X right, +Y up", kernelEnergyNormalization: "unit-energy-shape",
|
|
325
326
|
interpolation: "bounded-regular-grid-centroid-aligned", throughputOwnership: "separate-relative-pupil-throughput-factor",
|
|
326
|
-
responseIncludes: { diffraction: true, aberration: true, defocus: extra !== undefined, pupilClippingShape:
|
|
327
|
+
responseIncludes: { diffraction: true, aberration: true, defocus: extra !== undefined, pupilClippingShape: extra?.clipped === true },
|
|
327
328
|
sensorOpticalStackIncluded: false, sensorSamplingIncluded: false, reconstructionIncluded: false, strayLightIncluded: false,
|
|
328
329
|
axes: { focalLengthMm: [f], focusDiopters: [focusDiopters], apertureFNumber: [N], fieldXmm: fieldX, fieldYmm: fieldY, wavelengthNm: [...GENERIC_LENS_PSF_WAVELENGTHS_NM],
|
|
329
330
|
signedDefocusImagePlaneMicrometers: [0] }, nodes, evidence: input.evidence,
|
|
@@ -334,4 +335,26 @@ export function createGenericLensPsfProfile(input) {
|
|
|
334
335
|
transformSize: { minimum: minimumTransform, maximum: maximumTransform }, maximumPhaseStepWaves: phaseStep, fieldXmm: fieldX, fieldYmm: fieldY,
|
|
335
336
|
wavelengthsNm: [...GENERIC_LENS_PSF_WAVELENGTHS_NM] };
|
|
336
337
|
}
|
|
338
|
+
/**
|
|
339
|
+
* #567: the catalogue lens's own bokeh kernel for `lens.defocus` (#553's shaped kernel with `lens.character.bokeh`), as the
|
|
340
|
+
* PSF's field-dependent extra kernel. The defocus is referred to the lens's focus, the balanced one of its PSF (W020 = −W040):
|
|
341
|
+
* the ray map (σc/2 + bρ²)·P of the paraxial focus gains −(b/2)·P, so the kernel is #553's for the signed blur σc − b. Rows are
|
|
342
|
+
* flipped from #553's (+Y down) to the profile's (+Y up). With a cat's eye each field point (tangent x/f, y/f: the rectilinear
|
|
343
|
+
* chief ray, distortion neglected) has its own kernel, padded to the axis kernel's radius (clipping only narrows the blur). Each
|
|
344
|
+
* call builds its kernel (the profile calls it once per field and wavelength node: 125 small kernels). `catsEye` false leaves it out.
|
|
345
|
+
*/
|
|
346
|
+
export function genericLensBokehKernel(lens, diameterSites, side, pitch, catsEye) {
|
|
347
|
+
const b = lens.character.bokeh, options = (catsEye ? b : { blades: b.blades, sphericalAberration: b.sphericalAberration }), N = lens.character.fNumber, f = lens.focalLengthMm;
|
|
348
|
+
const s = side * diameterSites - 8 * N * options.sphericalAberration.w040Micrometers / pitch;
|
|
349
|
+
const build = (x, y) => createDefocusBokehSiteKernel({ diameterSites: Math.abs(s), side: s < 0 ? -1 : 1, fNumber: N,
|
|
350
|
+
focalLengthMm: f, pitchMicrometers: pitch, options, field: { x: x / f, y: y / f } });
|
|
351
|
+
const axis = build(0, 0), R = axis.radius, w = 2 * R + 1;
|
|
352
|
+
return { axis, radius: R, clipped: !!options.catsEye, at(x, y) {
|
|
353
|
+
const k = options.catsEye ? build(x, y) : axis, r = k.radius, out = new Float64Array(w * w);
|
|
354
|
+
for (let j = -r; j <= r; j++)
|
|
355
|
+
for (let i = -r; i <= r; i++)
|
|
356
|
+
out[(R - j) * w + i + R] = k.weights[(j + r) * k.width + i + r];
|
|
357
|
+
return out;
|
|
358
|
+
} };
|
|
359
|
+
}
|
|
337
360
|
//# sourceMappingURL=generic-lens-psf.js.map
|