@photivra/engine 1.4.0 → 2.0.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 +401 -6
- package/CITATION.cff +1 -1
- package/NODE_SUPPORT.md +64 -12
- package/README.md +301 -182
- package/SECURITY.md +37 -28
- package/THIRD_PARTY.md +148 -4
- package/dist/camera/equivalent-focal-length.d.ts +13 -14
- package/dist/camera/equivalent-focal-length.js +15 -13
- package/dist/camera/equivalent-focal-length.js.map +1 -1
- package/dist/camera/field-of-view.d.ts +30 -19
- package/dist/camera/field-of-view.js +67 -18
- package/dist/camera/field-of-view.js.map +1 -1
- package/dist/camera/lens-projection.d.ts +170 -0
- package/dist/camera/lens-projection.js +444 -0
- package/dist/camera/lens-projection.js.map +1 -0
- package/dist/camera/projected-object-size.d.ts +10 -11
- package/dist/camera/projected-object-size.js +12 -10
- package/dist/camera/projected-object-size.js.map +1 -1
- package/dist/capture/capture-export-metadata.d.ts +9 -10
- package/dist/capture/capture-export-metadata.js +8 -5
- package/dist/capture/capture-export-metadata.js.map +1 -1
- package/dist/capture/dng-import.d.ts +91 -0
- package/dist/capture/dng-import.js +343 -0
- package/dist/capture/dng-import.js.map +1 -0
- package/dist/capture/environment-raw-producer.d.ts +37 -17
- package/dist/capture/environment-raw-producer.js +43 -19
- package/dist/capture/environment-raw-producer.js.map +1 -1
- package/dist/capture/export-jpeg.d.ts +35 -4
- package/dist/capture/export-jpeg.js +133 -47
- package/dist/capture/export-jpeg.js.map +1 -1
- package/dist/capture/export-tiff.d.ts +48 -24
- package/dist/capture/export-tiff.js +91 -31
- package/dist/capture/export-tiff.js.map +1 -1
- package/dist/capture/focus-control.d.ts +42 -65
- package/dist/capture/focus-control.js +56 -75
- package/dist/capture/focus-control.js.map +1 -1
- package/dist/capture/host-yield-cadence.d.ts +25 -0
- package/dist/capture/host-yield-cadence.js +25 -0
- package/dist/capture/host-yield-cadence.js.map +1 -0
- package/dist/capture/linear-encoding.d.ts +14 -12
- package/dist/capture/linear-encoding.js +14 -13
- package/dist/capture/linear-encoding.js.map +1 -1
- package/dist/capture/lossless-jpeg.d.ts +27 -0
- package/dist/capture/lossless-jpeg.js +237 -0
- package/dist/capture/lossless-jpeg.js.map +1 -0
- package/dist/capture/native-environment-lean.d.ts +227 -0
- package/dist/capture/native-environment-lean.js +974 -0
- package/dist/capture/native-environment-lean.js.map +1 -0
- package/dist/capture/native-environment-optical-stage.d.ts +97 -0
- package/dist/capture/native-environment-optical-stage.js +340 -0
- package/dist/capture/native-environment-optical-stage.js.map +1 -0
- package/dist/capture/native-environment-raw.d.ts +140 -6
- package/dist/capture/native-environment-raw.js +435 -34
- package/dist/capture/native-environment-raw.js.map +1 -1
- package/dist/capture/native-raw-development.d.ts +118 -5
- package/dist/capture/native-raw-development.js +224 -59
- package/dist/capture/native-raw-development.js.map +1 -1
- package/dist/capture/native-raw-dng.d.ts +60 -0
- package/dist/capture/native-raw-dng.js +167 -0
- package/dist/capture/native-raw-dng.js.map +1 -0
- package/dist/capture/native-raw.d.ts +67 -10
- package/dist/capture/native-raw.js +90 -24
- package/dist/capture/native-raw.js.map +1 -1
- package/dist/capture/packed-sensor-raw.d.ts +160 -0
- package/dist/capture/packed-sensor-raw.js +221 -0
- package/dist/capture/packed-sensor-raw.js.map +1 -0
- package/dist/capture/photographic-export.d.ts +58 -35
- package/dist/capture/photographic-export.js +177 -70
- package/dist/capture/photographic-export.js.map +1 -1
- package/dist/capture/raw-development-kernel.d.ts +52 -0
- package/dist/capture/raw-development-kernel.js +88 -0
- package/dist/capture/raw-development-kernel.js.map +1 -0
- package/dist/capture/raw-frame-limits.d.ts +7 -7
- package/dist/capture/raw-frame-limits.js +7 -6
- package/dist/capture/raw-frame-limits.js.map +1 -1
- package/dist/capture/raw-frame-reconstruction.d.ts +8 -9
- package/dist/capture/raw-frame-reconstruction.js +9 -8
- package/dist/capture/raw-frame-reconstruction.js.map +1 -1
- package/dist/capture/raw-white-level.d.ts +55 -0
- package/dist/capture/raw-white-level.js +165 -0
- package/dist/capture/raw-white-level.js.map +1 -0
- package/dist/capture/release-sequence.d.ts +5 -7
- package/dist/capture/release-sequence.js +15 -13
- package/dist/capture/release-sequence.js.map +1 -1
- package/dist/capture/sensor-raw-frame.d.ts +5 -6
- package/dist/capture/sensor-raw-frame.js +26 -9
- package/dist/capture/sensor-raw-frame.js.map +1 -1
- package/dist/capture/sensor-raw-producer.d.ts +21 -13
- package/dist/capture/sensor-raw-producer.js +86 -25
- package/dist/capture/sensor-raw-producer.js.map +1 -1
- package/dist/capture/simulated-capture.d.ts +15 -16
- package/dist/capture/simulated-capture.js +22 -12
- package/dist/capture/simulated-capture.js.map +1 -1
- package/dist/color/camera-color-matrix.d.ts +69 -0
- package/dist/color/camera-color-matrix.js +132 -0
- package/dist/color/camera-color-matrix.js.map +1 -0
- package/dist/color/capture-color.d.ts +17 -10
- package/dist/color/capture-color.js +50 -17
- package/dist/color/capture-color.js.map +1 -1
- package/dist/color/chromatic-adaptation.d.ts +63 -0
- package/dist/color/chromatic-adaptation.js +91 -0
- package/dist/color/chromatic-adaptation.js.map +1 -0
- package/dist/color/color-difference.d.ts +104 -0
- package/dist/color/color-difference.js +205 -0
- package/dist/color/color-difference.js.map +1 -0
- package/dist/color/color-matching-functions.d.ts +168 -0
- package/dist/color/color-matching-functions.js +309 -0
- package/dist/color/color-matching-functions.js.map +1 -0
- package/dist/color/colorimetry-math.d.ts +52 -0
- package/dist/color/colorimetry-math.js +144 -0
- package/dist/color/colorimetry-math.js.map +1 -0
- package/dist/color/gamut-mapping.d.ts +54 -0
- package/dist/color/gamut-mapping.js +107 -0
- package/dist/color/gamut-mapping.js.map +1 -0
- package/dist/color/illuminants.d.ts +182 -0
- package/dist/color/illuminants.js +434 -0
- package/dist/color/illuminants.js.map +1 -0
- package/dist/color/rgb-color-spaces.d.ts +79 -0
- package/dist/color/rgb-color-spaces.js +115 -0
- package/dist/color/rgb-color-spaces.js.map +1 -0
- package/dist/color/sensor-color-development.d.ts +33 -11
- package/dist/color/sensor-color-development.js +104 -30
- package/dist/color/sensor-color-development.js.map +1 -1
- package/dist/color/srgb-icc.d.ts +9 -2
- package/dist/color/srgb-icc.js +16 -5
- package/dist/color/srgb-icc.js.map +1 -1
- package/dist/color/srgb-transfer.d.ts +1 -2
- package/dist/color/srgb-transfer.js +1 -1
- package/dist/color/srgb-transfer.js.map +1 -1
- package/dist/color/white-balance.d.ts +68 -19
- package/dist/color/white-balance.js +168 -35
- package/dist/color/white-balance.js.map +1 -1
- package/dist/composition/image-formation-plan.d.ts +152 -128
- package/dist/composition/image-formation-plan.js +292 -138
- package/dist/composition/image-formation-plan.js.map +1 -1
- package/dist/composition/plan-consumer.d.ts +6 -7
- package/dist/composition/plan-consumer.js +14 -11
- package/dist/composition/plan-consumer.js.map +1 -1
- package/dist/core/calculation-result.d.ts +21 -14
- package/dist/core/calculation-result.js +209 -11
- package/dist/core/calculation-result.js.map +1 -1
- package/dist/core/canonical-json.d.ts +13 -8
- package/dist/core/canonical-json.js +34 -15
- package/dist/core/canonical-json.js.map +1 -1
- package/dist/core/configuration-error.d.ts +5 -4
- package/dist/core/configuration-error.js +5 -3
- package/dist/core/configuration-error.js.map +1 -1
- package/dist/core/evidence-provenance.d.ts +12 -12
- package/dist/core/evidence-provenance.js +10 -9
- package/dist/core/evidence-provenance.js.map +1 -1
- package/dist/core/image-formation.d.ts +11 -10
- package/dist/core/image-formation.js +11 -9
- package/dist/core/image-formation.js.map +1 -1
- package/dist/core/owned-data.d.ts +9 -17
- package/dist/core/owned-data.js +9 -16
- package/dist/core/owned-data.js.map +1 -1
- package/dist/core/portable-math.d.ts +15 -0
- package/dist/core/portable-math.js +56 -0
- package/dist/core/portable-math.js.map +1 -0
- package/dist/core/record-validation.d.ts +48 -9
- package/dist/core/record-validation.js +93 -19
- package/dist/core/record-validation.js.map +1 -1
- package/dist/core/scientific-assurance.d.ts +16 -14
- package/dist/core/scientific-assurance.js +22 -18
- package/dist/core/scientific-assurance.js.map +1 -1
- package/dist/core/spectral-composition.d.ts +13 -14
- package/dist/core/spectral-composition.js +30 -27
- package/dist/core/spectral-composition.js.map +1 -1
- package/dist/core/spectral.d.ts +5 -6
- package/dist/core/spectral.js +9 -7
- package/dist/core/spectral.js.map +1 -1
- package/dist/core/validation.d.ts +3 -6
- package/dist/core/validation.js +3 -5
- package/dist/core/validation.js.map +1 -1
- package/dist/core/version.d.ts +6 -6
- package/dist/core/version.js +6 -5
- package/dist/core/version.js.map +1 -1
- package/dist/equipment/exposure-capabilities.d.ts +10 -10
- package/dist/equipment/exposure-capabilities.js +40 -30
- package/dist/equipment/exposure-capabilities.js.map +1 -1
- package/dist/equipment/generic-tier-assets.d.ts +13 -6
- package/dist/equipment/generic-tier-assets.js +34 -15
- package/dist/equipment/generic-tier-assets.js.map +1 -1
- package/dist/equipment/generic-tier-presets.d.ts +5 -6
- package/dist/equipment/generic-tier-presets.js +15 -13
- package/dist/equipment/generic-tier-presets.js.map +1 -1
- package/dist/equipment/iso-capabilities.d.ts +21 -22
- package/dist/equipment/iso-capabilities.js +49 -44
- package/dist/equipment/iso-capabilities.js.map +1 -1
- package/dist/equipment/metering-capabilities.d.ts +5 -6
- package/dist/equipment/metering-capabilities.js +22 -19
- package/dist/equipment/metering-capabilities.js.map +1 -1
- package/dist/equipment/release-capabilities.d.ts +3 -4
- package/dist/equipment/release-capabilities.js +18 -14
- package/dist/equipment/release-capabilities.js.map +1 -1
- package/dist/exposure/exposure-duration-control.d.ts +19 -17
- package/dist/exposure/exposure-duration-control.js +27 -23
- package/dist/exposure/exposure-duration-control.js.map +1 -1
- package/dist/exposure/exposure-mode-resolver.d.ts +42 -39
- package/dist/exposure/exposure-mode-resolver.js +127 -82
- package/dist/exposure/exposure-mode-resolver.js.map +1 -1
- package/dist/exposure/exposure.d.ts +17 -16
- package/dist/exposure/exposure.js +22 -15
- package/dist/exposure/exposure.js.map +1 -1
- package/dist/exposure/flash-ttl.d.ts +135 -0
- package/dist/exposure/flash-ttl.js +193 -0
- package/dist/exposure/flash-ttl.js.map +1 -0
- package/dist/exposure/flash.d.ts +144 -36
- package/dist/exposure/flash.js +259 -59
- package/dist/exposure/flash.js.map +1 -1
- package/dist/exposure/metering-scene-radiance.d.ts +10 -10
- package/dist/exposure/metering-scene-radiance.js +42 -23
- package/dist/exposure/metering-scene-radiance.js.map +1 -1
- package/dist/exposure/metering-target.d.ts +8 -8
- package/dist/exposure/metering-target.js +30 -20
- package/dist/exposure/metering-target.js.map +1 -1
- package/dist/exposure/metering-temporal.d.ts +16 -15
- package/dist/exposure/metering-temporal.js +41 -19
- package/dist/exposure/metering-temporal.js.map +1 -1
- package/dist/exposure/metering.d.ts +64 -17
- package/dist/exposure/metering.js +159 -30
- package/dist/exposure/metering.js.map +1 -1
- package/dist/exposure/program-line.d.ts +5 -5
- package/dist/exposure/program-line.js +20 -13
- package/dist/exposure/program-line.js.map +1 -1
- package/dist/facade/camera-preset.d.ts +8 -0
- package/dist/facade/camera-preset.js +102 -0
- package/dist/facade/camera-preset.js.map +1 -0
- package/dist/facade/chart-radiance-batch.d.ts +57 -0
- package/dist/facade/chart-radiance-batch.js +121 -0
- package/dist/facade/chart-radiance-batch.js.map +1 -0
- package/dist/facade/chart-scenes.d.ts +177 -0
- package/dist/facade/chart-scenes.js +232 -0
- package/dist/facade/chart-scenes.js.map +1 -0
- package/dist/facade/host-yield.d.ts +7 -0
- package/dist/facade/host-yield.js +23 -0
- package/dist/facade/host-yield.js.map +1 -0
- package/dist/facade/scene-radiance.d.ts +117 -0
- package/dist/facade/scene-radiance.js +205 -0
- package/dist/facade/scene-radiance.js.map +1 -0
- package/dist/facade/simulate-capture.d.ts +284 -0
- package/dist/facade/simulate-capture.js +1026 -0
- package/dist/facade/simulate-capture.js.map +1 -0
- package/dist/gpu/chart-radiance-gpu.d.ts +17 -0
- package/dist/gpu/chart-radiance-gpu.js +176 -0
- package/dist/gpu/chart-radiance-gpu.js.map +1 -0
- package/dist/gpu/image-kernel-accelerator.d.ts +132 -0
- package/dist/gpu/image-kernel-accelerator.js +720 -0
- package/dist/gpu/image-kernel-accelerator.js.map +1 -0
- package/dist/gpu/image-kernel-execution.d.ts +92 -0
- package/dist/gpu/image-kernel-execution.js +84 -0
- package/dist/gpu/image-kernel-execution.js.map +1 -0
- package/dist/gpu/sensor-stage-gpu.d.ts +44 -0
- package/dist/gpu/sensor-stage-gpu.js +317 -0
- package/dist/gpu/sensor-stage-gpu.js.map +1 -0
- package/dist/gpu/temporal-sum-gpu.d.ts +23 -0
- package/dist/gpu/temporal-sum-gpu.js +150 -0
- package/dist/gpu/temporal-sum-gpu.js.map +1 -0
- package/dist/gpu/webgpu-runtime.d.ts +63 -0
- package/dist/gpu/webgpu-runtime.js +215 -0
- package/dist/gpu/webgpu-runtime.js.map +1 -0
- package/dist/gpu/wgsl-chart-kernel.d.ts +30 -0
- package/dist/gpu/wgsl-chart-kernel.js +165 -0
- package/dist/gpu/wgsl-chart-kernel.js.map +1 -0
- package/dist/gpu/wgsl-kernels.d.ts +53 -0
- package/dist/gpu/wgsl-kernels.js +365 -0
- package/dist/gpu/wgsl-kernels.js.map +1 -0
- package/dist/gpu/wgsl-sensor-kernel.d.ts +64 -0
- package/dist/gpu/wgsl-sensor-kernel.js +409 -0
- package/dist/gpu/wgsl-sensor-kernel.js.map +1 -0
- package/dist/index.d.ts +89 -25
- package/dist/index.js +59 -15
- package/dist/index.js.map +1 -1
- package/dist/motion/camera-rotation.d.ts +92 -40
- package/dist/motion/camera-rotation.js +84 -47
- package/dist/motion/camera-rotation.js.map +1 -1
- package/dist/motion/capture-rotation-inverse-mapping.d.ts +37 -34
- package/dist/motion/capture-rotation-inverse-mapping.js +32 -24
- package/dist/motion/capture-rotation-inverse-mapping.js.map +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.d.ts +39 -35
- package/dist/motion/capture-rotation-temporal-quadrature.js +37 -28
- package/dist/motion/capture-rotation-temporal-quadrature.js.map +1 -1
- package/dist/motion/capture-rotation-trajectory.d.ts +32 -28
- package/dist/motion/capture-rotation-trajectory.js +36 -26
- package/dist/motion/capture-rotation-trajectory.js.map +1 -1
- package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts +23 -21
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js +33 -14
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js.map +1 -1
- package/dist/motion/extended-object-projection.d.ts +19 -16
- package/dist/motion/extended-object-projection.js +38 -18
- package/dist/motion/extended-object-projection.js.map +1 -1
- package/dist/motion/projected-motion.d.ts +18 -17
- package/dist/motion/projected-motion.js +25 -17
- package/dist/motion/projected-motion.js.map +1 -1
- package/dist/motion/temporal-exposure-sum.d.ts +55 -0
- package/dist/motion/temporal-exposure-sum.js +141 -0
- package/dist/motion/temporal-exposure-sum.js.map +1 -0
- package/dist/motion/video-sequence.d.ts +111 -0
- package/dist/motion/video-sequence.js +179 -0
- package/dist/motion/video-sequence.js.map +1 -0
- package/dist/optics/aperture.d.ts +14 -15
- package/dist/optics/aperture.js +13 -11
- package/dist/optics/aperture.js.map +1 -1
- package/dist/optics/atmospheric-haze.d.ts +83 -0
- package/dist/optics/atmospheric-haze.js +113 -0
- package/dist/optics/atmospheric-haze.js.map +1 -0
- package/dist/optics/brown-conrady-distortion.d.ts +116 -0
- package/dist/optics/brown-conrady-distortion.js +291 -0
- package/dist/optics/brown-conrady-distortion.js.map +1 -0
- package/dist/optics/circle-of-confusion.d.ts +10 -10
- package/dist/optics/circle-of-confusion.js +15 -11
- package/dist/optics/circle-of-confusion.js.map +1 -1
- package/dist/optics/complex-pupil-psf.d.ts +64 -33
- package/dist/optics/complex-pupil-psf.js +190 -98
- package/dist/optics/complex-pupil-psf.js.map +1 -1
- package/dist/optics/depth-of-field.d.ts +25 -15
- package/dist/optics/depth-of-field.js +67 -27
- package/dist/optics/depth-of-field.js.map +1 -1
- package/dist/optics/diffraction.d.ts +14 -13
- package/dist/optics/diffraction.js +14 -10
- package/dist/optics/diffraction.js.map +1 -1
- package/dist/optics/focus-breathing.d.ts +88 -27
- package/dist/optics/focus-breathing.js +114 -23
- package/dist/optics/focus-breathing.js.map +1 -1
- package/dist/optics/focus-state.d.ts +18 -18
- package/dist/optics/focus-state.js +21 -15
- package/dist/optics/focus-state.js.map +1 -1
- package/dist/optics/front-of-lens-filter.d.ts +45 -14
- package/dist/optics/front-of-lens-filter.js +259 -88
- package/dist/optics/front-of-lens-filter.js.map +1 -1
- package/dist/optics/illumination-vignetting.d.ts +16 -17
- package/dist/optics/illumination-vignetting.js +40 -17
- package/dist/optics/illumination-vignetting.js.map +1 -1
- package/dist/optics/irradiance-convolution.d.ts +59 -0
- package/dist/optics/irradiance-convolution.js +138 -0
- package/dist/optics/irradiance-convolution.js.map +1 -0
- package/dist/optics/lateral-chromatic-aberration.d.ts +33 -30
- package/dist/optics/lateral-chromatic-aberration.js +33 -23
- package/dist/optics/lateral-chromatic-aberration.js.map +1 -1
- package/dist/optics/lens-psf-kernels.d.ts +89 -0
- package/dist/optics/lens-psf-kernels.js +175 -0
- package/dist/optics/lens-psf-kernels.js.map +1 -0
- package/dist/optics/lens-psf-profile.d.ts +78 -46
- package/dist/optics/lens-psf-profile.js +335 -124
- package/dist/optics/lens-psf-profile.js.map +1 -1
- package/dist/optics/longitudinal-chromatic-aberration.d.ts +102 -0
- package/dist/optics/longitudinal-chromatic-aberration.js +210 -0
- package/dist/optics/longitudinal-chromatic-aberration.js.map +1 -0
- package/dist/optics/polygon-diffraction.d.ts +80 -23
- package/dist/optics/polygon-diffraction.js +130 -25
- package/dist/optics/polygon-diffraction.js.map +1 -1
- package/dist/optics/profile-contract.d.ts +5 -6
- package/dist/optics/profile-contract.js +14 -11
- package/dist/optics/profile-contract.js.map +1 -1
- package/dist/optics/psf-foundation.d.ts +23 -23
- package/dist/optics/psf-foundation.js +24 -21
- package/dist/optics/psf-foundation.js.map +1 -1
- package/dist/optics/pupil-vignetting.d.ts +118 -0
- package/dist/optics/pupil-vignetting.js +264 -0
- package/dist/optics/pupil-vignetting.js.map +1 -0
- package/dist/optics/radial-distortion.d.ts +34 -33
- package/dist/optics/radial-distortion.js +37 -30
- package/dist/optics/radial-distortion.js.map +1 -1
- package/dist/optics/scene-to-sensor-irradiance.d.ts +47 -33
- package/dist/optics/scene-to-sensor-irradiance.js +73 -45
- package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
- package/dist/optics/scene-to-sensor-quadrature.d.ts +23 -18
- package/dist/optics/scene-to-sensor-quadrature.js +16 -11
- package/dist/optics/scene-to-sensor-quadrature.js.map +1 -1
- package/dist/optics/sensor-aperture-rays.d.ts +20 -4
- package/dist/optics/sensor-aperture-rays.js +32 -14
- package/dist/optics/sensor-aperture-rays.js.map +1 -1
- package/dist/optics/sensor-environment-query.d.ts +81 -16
- package/dist/optics/sensor-environment-query.js +145 -12
- package/dist/optics/sensor-environment-query.js.map +1 -1
- package/dist/optics/sensor-psf-quadrature.d.ts +12 -10
- package/dist/optics/sensor-psf-quadrature.js +18 -11
- package/dist/optics/sensor-psf-quadrature.js.map +1 -1
- package/dist/optics/sensor-psf-support.d.ts +8 -6
- package/dist/optics/sensor-psf-support.js +8 -5
- package/dist/optics/sensor-psf-support.js.map +1 -1
- package/dist/optics/stray-light.d.ts +22 -19
- package/dist/optics/stray-light.js +18 -12
- package/dist/optics/stray-light.js.map +1 -1
- package/dist/optics/thin-lens.d.ts +10 -9
- package/dist/optics/thin-lens.js +12 -8
- package/dist/optics/thin-lens.js.map +1 -1
- package/dist/optics/zernike-wavefront.d.ts +154 -0
- package/dist/optics/zernike-wavefront.js +352 -0
- package/dist/optics/zernike-wavefront.js.map +1 -0
- package/dist/output/capture-corrected-sdr.d.ts +16 -8
- package/dist/output/capture-corrected-sdr.js +16 -8
- package/dist/output/capture-corrected-sdr.js.map +1 -1
- package/dist/output/capture-geometry.d.ts +34 -36
- package/dist/output/capture-geometry.js +52 -32
- package/dist/output/capture-geometry.js.map +1 -1
- package/dist/output/capture-sdr.d.ts +7 -6
- package/dist/output/capture-sdr.js +11 -8
- package/dist/output/capture-sdr.js.map +1 -1
- package/dist/output/crop.d.ts +22 -6
- package/dist/output/crop.js +40 -6
- package/dist/output/crop.js.map +1 -1
- package/dist/output/geometric-transforms.d.ts +60 -23
- package/dist/output/geometric-transforms.js +111 -24
- package/dist/output/geometric-transforms.js.map +1 -1
- package/dist/output/lens-corrections.d.ts +27 -19
- package/dist/output/lens-corrections.js +29 -13
- package/dist/output/lens-corrections.js.map +1 -1
- package/dist/output/native-capture-sdr.d.ts +71 -16
- package/dist/output/native-capture-sdr.js +190 -33
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/output/png-encoder.d.ts +65 -0
- package/dist/output/png-encoder.js +461 -0
- package/dist/output/png-encoder.js.map +1 -0
- package/dist/output/print-contrast-reference.d.ts +10 -9
- package/dist/output/print-contrast-reference.js +10 -8
- package/dist/output/print-contrast-reference.js.map +1 -1
- package/dist/output/print-detail.d.ts +18 -17
- package/dist/output/print-detail.js +12 -10
- package/dist/output/print-detail.js.map +1 -1
- package/dist/output/print-jpeg.d.ts +26 -5
- package/dist/output/print-jpeg.js +117 -50
- package/dist/output/print-jpeg.js.map +1 -1
- package/dist/output/print-plan.d.ts +19 -19
- package/dist/output/print-plan.js +11 -10
- package/dist/output/print-plan.js.map +1 -1
- package/dist/output/print-region-statistics.d.ts +14 -15
- package/dist/output/print-region-statistics.js +11 -11
- package/dist/output/print-region-statistics.js.map +1 -1
- package/dist/output/sdr-rendering.d.ts +48 -10
- package/dist/output/sdr-rendering.js +114 -25
- package/dist/output/sdr-rendering.js.map +1 -1
- package/dist/output/subject-framing-crop.d.ts +6 -10
- package/dist/output/subject-framing-crop.js +23 -13
- package/dist/output/subject-framing-crop.js.map +1 -1
- package/dist/processing/demosaic.d.ts +90 -0
- package/dist/processing/demosaic.js +275 -0
- package/dist/processing/demosaic.js.map +1 -0
- package/dist/processing/denoise.d.ts +68 -0
- package/dist/processing/denoise.js +214 -0
- package/dist/processing/denoise.js.map +1 -0
- package/dist/processing/focus-stacking.d.ts +17 -0
- package/dist/processing/focus-stacking.js +80 -0
- package/dist/processing/focus-stacking.js.map +1 -0
- package/dist/processing/hdr.d.ts +54 -0
- package/dist/processing/hdr.js +172 -0
- package/dist/processing/hdr.js.map +1 -0
- package/dist/processing/image-ops.d.ts +66 -0
- package/dist/processing/image-ops.js +192 -0
- package/dist/processing/image-ops.js.map +1 -0
- package/dist/processing/panorama.d.ts +51 -0
- package/dist/processing/panorama.js +305 -0
- package/dist/processing/panorama.js.map +1 -0
- package/dist/processing/processing-task.d.ts +85 -0
- package/dist/processing/processing-task.js +164 -0
- package/dist/processing/processing-task.js.map +1 -0
- package/dist/processing/tone-mapping.d.ts +69 -0
- package/dist/processing/tone-mapping.js +310 -0
- package/dist/processing/tone-mapping.js.map +1 -0
- package/dist/schema/camera.d.ts +5 -4
- package/dist/schema/illumination-spectral.d.ts +13 -19
- package/dist/schema/illumination-spectral.js +23 -19
- package/dist/schema/illumination-spectral.js.map +1 -1
- package/dist/schema/illumination-temporal.d.ts +12 -15
- package/dist/schema/illumination-temporal.js +43 -28
- package/dist/schema/illumination-temporal.js.map +1 -1
- package/dist/schema/illumination.d.ts +5 -4
- package/dist/schema/illumination.js +55 -20
- package/dist/schema/illumination.js.map +1 -1
- package/dist/schema/scene-radiance-temporal.d.ts +9 -11
- package/dist/schema/scene-radiance-temporal.js +26 -23
- package/dist/schema/scene-radiance-temporal.js.map +1 -1
- package/dist/schema/scene-radiance.d.ts +17 -17
- package/dist/schema/scene-radiance.js +56 -34
- package/dist/schema/scene-radiance.js.map +1 -1
- package/dist/schema/scene.d.ts +14 -13
- package/dist/schema/validation.d.ts +0 -1
- package/dist/schema/validation.js +17 -15
- package/dist/schema/validation.js.map +1 -1
- package/dist/sensor/accumulated-charge.d.ts +45 -64
- package/dist/sensor/accumulated-charge.js +41 -47
- package/dist/sensor/accumulated-charge.js.map +1 -1
- package/dist/sensor/architecture.d.ts +22 -25
- package/dist/sensor/architecture.js +17 -16
- package/dist/sensor/architecture.js.map +1 -1
- package/dist/sensor/camera-saturation-capacity.d.ts +21 -28
- package/dist/sensor/camera-saturation-capacity.js +36 -34
- package/dist/sensor/camera-saturation-capacity.js.map +1 -1
- package/dist/sensor/capture-color-sampling-binding.d.ts +46 -51
- package/dist/sensor/capture-color-sampling-binding.js +39 -41
- package/dist/sensor/capture-color-sampling-binding.js.map +1 -1
- package/dist/sensor/capture-mode-timing.d.ts +8 -9
- package/dist/sensor/capture-mode-timing.js +24 -21
- package/dist/sensor/capture-mode-timing.js.map +1 -1
- package/dist/sensor/capture-mode.d.ts +28 -30
- package/dist/sensor/capture-mode.js +33 -31
- package/dist/sensor/capture-mode.js.map +1 -1
- package/dist/sensor/color-sampling.d.ts +30 -33
- package/dist/sensor/color-sampling.js +32 -37
- package/dist/sensor/color-sampling.js.map +1 -1
- package/dist/sensor/constant-rate-temporal-integration.d.ts +19 -23
- package/dist/sensor/constant-rate-temporal-integration.js +28 -26
- package/dist/sensor/constant-rate-temporal-integration.js.map +1 -1
- package/dist/sensor/dark-current.d.ts +53 -49
- package/dist/sensor/dark-current.js +87 -46
- package/dist/sensor/dark-current.js.map +1 -1
- package/dist/sensor/environment-photo-signal.d.ts +71 -30
- package/dist/sensor/environment-photo-signal.js +127 -46
- package/dist/sensor/environment-photo-signal.js.map +1 -1
- package/dist/sensor/eqe-electron-rate.d.ts +14 -13
- package/dist/sensor/eqe-electron-rate.js +34 -14
- package/dist/sensor/eqe-electron-rate.js.map +1 -1
- package/dist/sensor/eqe-local-exposure.d.ts +24 -24
- package/dist/sensor/eqe-local-exposure.js +15 -11
- package/dist/sensor/eqe-local-exposure.js.map +1 -1
- package/dist/sensor/eqe-temporal-exposure.d.ts +11 -11
- package/dist/sensor/eqe-temporal-exposure.js +15 -10
- package/dist/sensor/eqe-temporal-exposure.js.map +1 -1
- package/dist/sensor/exposure-window.d.ts +48 -34
- package/dist/sensor/exposure-window.js +77 -36
- package/dist/sensor/exposure-window.js.map +1 -1
- package/dist/sensor/fixed-pattern-noise.d.ts +108 -0
- package/dist/sensor/fixed-pattern-noise.js +166 -0
- package/dist/sensor/fixed-pattern-noise.js.map +1 -0
- package/dist/sensor/iso-gain.d.ts +44 -0
- package/dist/sensor/iso-gain.js +119 -0
- package/dist/sensor/iso-gain.js.map +1 -0
- package/dist/sensor/iso-signal-chain.d.ts +25 -48
- package/dist/sensor/iso-signal-chain.js +52 -66
- package/dist/sensor/iso-signal-chain.js.map +1 -1
- package/dist/sensor/local-exposure-binding.d.ts +21 -21
- package/dist/sensor/local-exposure-binding.js +22 -18
- package/dist/sensor/local-exposure-binding.js.map +1 -1
- package/dist/sensor/optical-stack.d.ts +36 -40
- package/dist/sensor/optical-stack.js +34 -37
- package/dist/sensor/optical-stack.js.map +1 -1
- package/dist/sensor/photon-energy.d.ts +22 -28
- package/dist/sensor/photon-energy.js +42 -34
- package/dist/sensor/photon-energy.js.map +1 -1
- package/dist/sensor/physical-charge-capacity.d.ts +20 -30
- package/dist/sensor/physical-charge-capacity.js +35 -36
- package/dist/sensor/physical-charge-capacity.js.map +1 -1
- package/dist/sensor/pixel-pitch.d.ts +2 -3
- package/dist/sensor/pixel-pitch.js +4 -2
- package/dist/sensor/pixel-pitch.js.map +1 -1
- package/dist/sensor/radiometry-readiness.d.ts +13 -15
- package/dist/sensor/radiometry-readiness.js +20 -17
- package/dist/sensor/radiometry-readiness.js.map +1 -1
- package/dist/sensor/raw-readout.d.ts +173 -83
- package/dist/sensor/raw-readout.js +425 -160
- package/dist/sensor/raw-readout.js.map +1 -1
- package/dist/sensor/raw-reconstruction.d.ts +112 -44
- package/dist/sensor/raw-reconstruction.js +200 -47
- package/dist/sensor/raw-reconstruction.js.map +1 -1
- package/dist/sensor/readout-exposure-linkage.d.ts +103 -34
- package/dist/sensor/readout-exposure-linkage.js +125 -27
- package/dist/sensor/readout-exposure-linkage.js.map +1 -1
- package/dist/sensor/readout-timing.d.ts +43 -44
- package/dist/sensor/readout-timing.js +38 -30
- package/dist/sensor/readout-timing.js.map +1 -1
- package/dist/sensor/response-application-compatibility.d.ts +21 -28
- package/dist/sensor/response-application-compatibility.js +35 -34
- package/dist/sensor/response-application-compatibility.js.map +1 -1
- package/dist/sensor/response-operating-range.d.ts +26 -35
- package/dist/sensor/response-operating-range.js +40 -39
- package/dist/sensor/response-operating-range.js.map +1 -1
- package/dist/sensor/responsivity-photocurrent.d.ts +21 -29
- package/dist/sensor/responsivity-photocurrent.js +57 -40
- package/dist/sensor/responsivity-photocurrent.js.map +1 -1
- package/dist/sensor/sampling-aperture.d.ts +21 -25
- package/dist/sensor/sampling-aperture.js +29 -28
- package/dist/sensor/sampling-aperture.js.map +1 -1
- package/dist/sensor/scene-eqe-temporal-exposure.d.ts +14 -12
- package/dist/sensor/scene-eqe-temporal-exposure.js +13 -8
- package/dist/sensor/scene-eqe-temporal-exposure.js.map +1 -1
- package/dist/sensor/sensor-geometry.d.ts +28 -32
- package/dist/sensor/sensor-geometry.js +35 -20
- package/dist/sensor/sensor-geometry.js.map +1 -1
- package/dist/sensor/signal-noise.d.ts +14 -16
- package/dist/sensor/signal-noise.js +15 -13
- package/dist/sensor/signal-noise.js.map +1 -1
- package/dist/sensor/spatial-sample-reduction.d.ts +45 -60
- package/dist/sensor/spatial-sample-reduction.js +39 -48
- package/dist/sensor/spatial-sample-reduction.js.map +1 -1
- package/dist/sensor/spatial-sampling-quadrature.d.ts +46 -54
- package/dist/sensor/spatial-sampling-quadrature.js +31 -36
- package/dist/sensor/spatial-sampling-quadrature.js.map +1 -1
- package/dist/sensor/spatio-spectral-reduction.d.ts +32 -42
- package/dist/sensor/spatio-spectral-reduction.js +24 -29
- package/dist/sensor/spatio-spectral-reduction.js.map +1 -1
- package/dist/sensor/spectral-coverage.d.ts +6 -9
- package/dist/sensor/spectral-coverage.js +9 -6
- package/dist/sensor/spectral-coverage.js.map +1 -1
- package/dist/sensor/spectral-quadrature.d.ts +46 -60
- package/dist/sensor/spectral-quadrature.js +38 -48
- package/dist/sensor/spectral-quadrature.js.map +1 -1
- package/dist/sensor/spectral-response.d.ts +53 -41
- package/dist/sensor/spectral-response.js +80 -47
- package/dist/sensor/spectral-response.js.map +1 -1
- package/dist/sensor/stochastic-seed.d.ts +50 -0
- package/dist/sensor/stochastic-seed.js +123 -0
- package/dist/sensor/stochastic-seed.js.map +1 -0
- package/dist/sensor/temporal-eqe-sum.d.ts +2 -4
- package/dist/sensor/temporal-eqe-sum.js +5 -6
- package/dist/sensor/temporal-eqe-sum.js.map +1 -1
- package/dist/sensor/temporal-photo-signal.d.ts +5 -6
- package/dist/sensor/temporal-photo-signal.js +11 -10
- package/dist/sensor/temporal-photo-signal.js.map +1 -1
- package/dist/sensor/temporal-sample-binding.d.ts +1 -2
- package/dist/sensor/temporal-sample-binding.js +3 -3
- package/dist/sensor/temporal-sample-binding.js.map +1 -1
- package/dist/simulation/poc-simulation.d.ts +16 -16
- package/dist/simulation/poc-simulation.js +20 -15
- package/dist/simulation/poc-simulation.js.map +1 -1
- package/dist/stabilization/camera-shake.d.ts +42 -18
- package/dist/stabilization/camera-shake.js +43 -20
- package/dist/stabilization/camera-shake.js.map +1 -1
- package/dist/stabilization/system.d.ts +44 -41
- package/dist/stabilization/system.js +196 -108
- package/dist/stabilization/system.js.map +1 -1
- package/docs/AGENT_GUIDE.md +183 -0
- package/docs/API_REFERENCE.md +761 -2
- package/docs/QUICK_START.md +495 -0
- package/docs/USAGE.md +1719 -714
- package/docs/api/camera-equivalent-focal-length.md +6 -7
- package/docs/api/camera-field-of-view.md +16 -8
- package/docs/api/camera-lens-projection.md +246 -0
- package/docs/api/camera-projected-object-size.md +6 -5
- package/docs/api/capture-capture-export-metadata.md +10 -10
- package/docs/api/capture-dng-import.md +134 -0
- package/docs/api/capture-environment-raw-producer.md +17 -11
- package/docs/api/capture-export-jpeg.md +16 -0
- package/docs/api/capture-focus-control.md +25 -47
- package/docs/api/capture-linear-encoding.md +21 -12
- package/docs/api/capture-lossless-jpeg.md +49 -0
- package/docs/api/capture-native-environment-optical-stage.md +75 -0
- package/docs/api/capture-native-environment-raw.md +161 -4
- package/docs/api/capture-native-raw-development.md +69 -4
- package/docs/api/capture-native-raw-dng.md +84 -0
- package/docs/api/capture-native-raw.md +23 -8
- package/docs/api/capture-packed-sensor-raw.md +156 -0
- package/docs/api/capture-photographic-export.md +69 -31
- package/docs/api/capture-raw-frame-reconstruction.md +8 -8
- package/docs/api/capture-raw-white-level.md +37 -0
- package/docs/api/capture-release-sequence.md +6 -7
- package/docs/api/capture-sensor-raw-frame.md +6 -6
- package/docs/api/capture-sensor-raw-producer.md +17 -11
- package/docs/api/capture-simulated-capture.md +15 -15
- package/docs/api/color-camera-color-matrix.md +103 -0
- package/docs/api/color-capture-color.md +22 -11
- package/docs/api/color-chromatic-adaptation.md +82 -0
- package/docs/api/color-color-difference.md +134 -0
- package/docs/api/color-color-matching-functions.md +259 -0
- package/docs/api/color-colorimetry-math.md +54 -0
- package/docs/api/color-gamut-mapping.md +72 -0
- package/docs/api/color-illuminants.md +280 -0
- package/docs/api/color-rgb-color-spaces.md +151 -0
- package/docs/api/color-sensor-color-development.md +27 -0
- package/docs/api/color-srgb-icc.md +2 -4
- package/docs/api/color-white-balance.md +95 -19
- package/docs/api/composition-image-formation-plan.md +124 -95
- package/docs/api/composition-plan-consumer.md +7 -7
- package/docs/api/core-calculation-result.md +18 -14
- package/docs/api/core-configuration-error.md +1 -1
- package/docs/api/core-image-formation.md +7 -7
- package/docs/api/core-scientific-assurance.md +12 -10
- package/docs/api/core-spectral-composition.md +14 -14
- package/docs/api/core-spectral.md +6 -6
- package/docs/api/core-validation.md +3 -3
- package/docs/api/core-version.md +7 -6
- package/docs/api/equipment-exposure-capabilities.md +11 -10
- package/docs/api/equipment-generic-tier-assets.md +7 -2
- package/docs/api/equipment-generic-tier-presets.md +6 -6
- package/docs/api/equipment-iso-capabilities.md +18 -18
- package/docs/api/equipment-metering-capabilities.md +6 -6
- package/docs/api/equipment-release-capabilities.md +4 -4
- package/docs/api/exports.json +2213 -8
- package/docs/api/exposure-exposure-duration-control.md +9 -9
- package/docs/api/exposure-exposure-mode-resolver.md +35 -31
- package/docs/api/exposure-exposure.md +10 -10
- package/docs/api/exposure-flash-ttl.md +182 -0
- package/docs/api/exposure-flash.md +183 -28
- package/docs/api/exposure-metering-scene-radiance.md +11 -10
- package/docs/api/exposure-metering-target.md +9 -8
- package/docs/api/exposure-metering-temporal.md +8 -8
- package/docs/api/exposure-metering.md +69 -9
- package/docs/api/exposure-program-line.md +6 -5
- package/docs/api/facade-chart-radiance-batch.md +96 -0
- package/docs/api/facade-chart-scenes.md +240 -0
- package/docs/api/facade-scene-radiance.md +122 -0
- package/docs/api/facade-simulate-capture.md +324 -0
- package/docs/api/gpu-image-kernel-accelerator.md +157 -0
- package/docs/api/gpu-image-kernel-execution.md +152 -0
- package/docs/api/motion-camera-rotation.md +43 -26
- package/docs/api/motion-capture-rotation-inverse-mapping.md +24 -23
- package/docs/api/motion-capture-rotation-temporal-quadrature.md +22 -22
- package/docs/api/motion-capture-rotation-trajectory.md +15 -15
- package/docs/api/motion-capture-translation-parallax-temporal-quadrature.md +15 -14
- package/docs/api/motion-extended-object-projection.md +10 -8
- package/docs/api/motion-projected-motion.md +8 -8
- package/docs/api/motion-temporal-exposure-sum.md +98 -0
- package/docs/api/motion-video-sequence.md +159 -0
- package/docs/api/optics-aperture.md +8 -8
- package/docs/api/optics-atmospheric-haze.md +104 -0
- package/docs/api/optics-brown-conrady-distortion.md +123 -0
- package/docs/api/optics-circle-of-confusion.md +5 -4
- package/docs/api/optics-complex-pupil-psf.md +57 -16
- package/docs/api/optics-depth-of-field.md +12 -6
- package/docs/api/optics-diffraction.md +8 -7
- package/docs/api/optics-focus-breathing.md +104 -16
- package/docs/api/optics-focus-state.md +9 -10
- package/docs/api/optics-front-of-lens-filter.md +72 -14
- package/docs/api/optics-illumination-vignetting.md +10 -10
- package/docs/api/optics-irradiance-convolution.md +95 -0
- package/docs/api/optics-lateral-chromatic-aberration.md +22 -21
- package/docs/api/optics-lens-psf-kernels.md +72 -0
- package/docs/api/optics-lens-psf-profile.md +48 -26
- package/docs/api/optics-longitudinal-chromatic-aberration.md +128 -0
- package/docs/api/optics-polygon-diffraction.md +78 -13
- package/docs/api/optics-profile-contract.md +4 -4
- package/docs/api/optics-psf-foundation.md +12 -12
- package/docs/api/optics-pupil-vignetting.md +132 -0
- package/docs/api/optics-radial-distortion.md +12 -12
- package/docs/api/optics-scene-to-sensor-irradiance.md +25 -14
- package/docs/api/optics-scene-to-sensor-quadrature.md +15 -12
- package/docs/api/optics-sensor-aperture-rays.md +3 -2
- package/docs/api/optics-sensor-environment-query.md +52 -9
- package/docs/api/optics-sensor-psf-quadrature.md +13 -10
- package/docs/api/optics-stray-light.md +12 -11
- package/docs/api/optics-thin-lens.md +4 -3
- package/docs/api/optics-zernike-wavefront.md +229 -0
- package/docs/api/output-capture-corrected-sdr.md +10 -7
- package/docs/api/output-capture-geometry.md +35 -36
- package/docs/api/output-capture-sdr.md +4 -4
- package/docs/api/output-crop.md +7 -4
- package/docs/api/output-geometric-transforms.md +65 -19
- package/docs/api/output-lens-corrections.md +17 -15
- package/docs/api/output-native-capture-sdr.md +26 -13
- package/docs/api/output-png-encoder.md +105 -0
- package/docs/api/output-print-contrast-reference.md +8 -8
- package/docs/api/output-print-detail.md +14 -14
- package/docs/api/output-print-jpeg.md +22 -5
- package/docs/api/output-print-plan.md +18 -18
- package/docs/api/output-print-region-statistics.md +14 -14
- package/docs/api/output-sdr-rendering.md +52 -10
- package/docs/api/output-subject-framing-crop.md +5 -6
- package/docs/api/processing-demosaic.md +120 -0
- package/docs/api/processing-denoise.md +148 -0
- package/docs/api/processing-focus-stacking.md +41 -0
- package/docs/api/processing-hdr.md +113 -0
- package/docs/api/processing-panorama.md +82 -0
- package/docs/api/processing-processing-task.md +107 -0
- package/docs/api/processing-tone-mapping.md +142 -0
- package/docs/api/schema-camera.md +6 -4
- package/docs/api/schema-illumination-spectral.md +10 -11
- package/docs/api/schema-illumination-temporal.md +13 -15
- package/docs/api/schema-illumination.md +4 -4
- package/docs/api/schema-scene-radiance-temporal.md +10 -11
- package/docs/api/schema-scene-radiance.md +18 -17
- package/docs/api/schema-scene.md +9 -9
- package/docs/api/schema-validation.md +1 -1
- package/docs/api/sensor-accumulated-charge.md +12 -20
- package/docs/api/sensor-architecture.md +15 -16
- package/docs/api/sensor-camera-saturation-capacity.md +9 -11
- package/docs/api/sensor-capture-color-sampling-binding.md +47 -51
- package/docs/api/sensor-capture-mode-timing.md +9 -9
- package/docs/api/sensor-capture-mode.md +29 -30
- package/docs/api/sensor-color-sampling.md +31 -33
- package/docs/api/sensor-constant-rate-temporal-integration.md +10 -11
- package/docs/api/sensor-dark-current.md +30 -14
- package/docs/api/sensor-environment-photo-signal.md +13 -6
- package/docs/api/sensor-eqe-electron-rate.md +9 -8
- package/docs/api/sensor-eqe-local-exposure.md +18 -17
- package/docs/api/sensor-eqe-temporal-exposure.md +12 -11
- package/docs/api/sensor-exposure-window.md +24 -24
- package/docs/api/sensor-fixed-pattern-noise.md +104 -0
- package/docs/api/sensor-iso-gain.md +63 -0
- package/docs/api/sensor-iso-signal-chain.md +13 -22
- package/docs/api/sensor-local-exposure-binding.md +12 -13
- package/docs/api/sensor-optical-stack.md +37 -40
- package/docs/api/sensor-photon-energy.md +10 -11
- package/docs/api/sensor-physical-charge-capacity.md +8 -13
- package/docs/api/sensor-pixel-pitch.md +1 -1
- package/docs/api/sensor-radiometry-readiness.md +9 -9
- package/docs/api/sensor-raw-readout.md +118 -52
- package/docs/api/sensor-raw-reconstruction.md +97 -20
- package/docs/api/sensor-readout-exposure-linkage.md +120 -24
- package/docs/api/sensor-readout-timing.md +33 -35
- package/docs/api/sensor-response-application-compatibility.md +9 -11
- package/docs/api/sensor-response-operating-range.md +14 -18
- package/docs/api/sensor-responsivity-photocurrent.md +9 -12
- package/docs/api/sensor-sampling-aperture.md +22 -25
- package/docs/api/sensor-scene-eqe-temporal-exposure.md +9 -8
- package/docs/api/sensor-sensor-geometry.md +23 -24
- package/docs/api/sensor-signal-noise.md +10 -10
- package/docs/api/sensor-spatial-sample-reduction.md +27 -30
- package/docs/api/sensor-spatial-sampling-quadrature.md +37 -39
- package/docs/api/sensor-spatio-spectral-reduction.md +27 -29
- package/docs/api/sensor-spectral-coverage.md +5 -5
- package/docs/api/sensor-spectral-quadrature.md +33 -35
- package/docs/api/sensor-spectral-response.md +28 -16
- package/docs/api/sensor-temporal-photo-signal.md +6 -6
- package/docs/api/simulation-poc-simulation.md +17 -16
- package/docs/api/stabilization-camera-shake.md +29 -10
- package/docs/api/stabilization-system.md +25 -21
- package/docs/examples/production-request.json +3821 -2157
- package/docs/examples/simulate-capture.mjs +14 -0
- package/llms.txt +35 -0
- package/package.json +32 -12
- package/AGENTS.md +0 -674
- package/CONTRIBUTING.md +0 -76
- package/DCO +0 -33
- package/dist/camera/equivalent-focal-length.d.ts.map +0 -1
- package/dist/camera/field-of-view.d.ts.map +0 -1
- package/dist/camera/projected-object-size.d.ts.map +0 -1
- package/dist/capture/capture-export-metadata.d.ts.map +0 -1
- package/dist/capture/environment-raw-producer.d.ts.map +0 -1
- package/dist/capture/export-jpeg.d.ts.map +0 -1
- package/dist/capture/export-tiff.d.ts.map +0 -1
- package/dist/capture/focus-control.d.ts.map +0 -1
- package/dist/capture/linear-encoding.d.ts.map +0 -1
- package/dist/capture/native-environment-raw.d.ts.map +0 -1
- package/dist/capture/native-raw-development.d.ts.map +0 -1
- package/dist/capture/native-raw.d.ts.map +0 -1
- package/dist/capture/photographic-export.d.ts.map +0 -1
- package/dist/capture/raw-frame-limits.d.ts.map +0 -1
- package/dist/capture/raw-frame-reconstruction.d.ts.map +0 -1
- package/dist/capture/release-sequence.d.ts.map +0 -1
- package/dist/capture/sensor-raw-frame.d.ts.map +0 -1
- package/dist/capture/sensor-raw-producer.d.ts.map +0 -1
- package/dist/capture/simulated-capture.d.ts.map +0 -1
- package/dist/color/capture-color.d.ts.map +0 -1
- package/dist/color/sensor-color-development.d.ts.map +0 -1
- package/dist/color/srgb-icc.d.ts.map +0 -1
- package/dist/color/srgb-transfer.d.ts.map +0 -1
- package/dist/color/white-balance.d.ts.map +0 -1
- package/dist/composition/image-formation-plan.d.ts.map +0 -1
- package/dist/composition/plan-consumer.d.ts.map +0 -1
- package/dist/core/calculation-result.d.ts.map +0 -1
- package/dist/core/canonical-json.d.ts.map +0 -1
- package/dist/core/configuration-error.d.ts.map +0 -1
- package/dist/core/evidence-provenance.d.ts.map +0 -1
- package/dist/core/image-formation.d.ts.map +0 -1
- package/dist/core/owned-data.d.ts.map +0 -1
- package/dist/core/record-validation.d.ts.map +0 -1
- package/dist/core/scientific-assurance.d.ts.map +0 -1
- package/dist/core/spectral-composition.d.ts.map +0 -1
- package/dist/core/spectral.d.ts.map +0 -1
- package/dist/core/validation.d.ts.map +0 -1
- package/dist/core/version.d.ts.map +0 -1
- package/dist/equipment/exposure-capabilities.d.ts.map +0 -1
- package/dist/equipment/generic-tier-assets.d.ts.map +0 -1
- package/dist/equipment/generic-tier-presets.d.ts.map +0 -1
- package/dist/equipment/iso-capabilities.d.ts.map +0 -1
- package/dist/equipment/metering-capabilities.d.ts.map +0 -1
- package/dist/equipment/release-capabilities.d.ts.map +0 -1
- package/dist/exposure/exposure-duration-control.d.ts.map +0 -1
- package/dist/exposure/exposure-mode-resolver.d.ts.map +0 -1
- package/dist/exposure/exposure.d.ts.map +0 -1
- package/dist/exposure/flash.d.ts.map +0 -1
- package/dist/exposure/metering-scene-radiance.d.ts.map +0 -1
- package/dist/exposure/metering-target.d.ts.map +0 -1
- package/dist/exposure/metering-temporal.d.ts.map +0 -1
- package/dist/exposure/metering.d.ts.map +0 -1
- package/dist/exposure/program-line.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/motion/camera-rotation.d.ts.map +0 -1
- package/dist/motion/capture-rotation-inverse-mapping.d.ts.map +0 -1
- package/dist/motion/capture-rotation-temporal-quadrature.d.ts.map +0 -1
- package/dist/motion/capture-rotation-trajectory.d.ts.map +0 -1
- package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts.map +0 -1
- package/dist/motion/extended-object-projection.d.ts.map +0 -1
- package/dist/motion/projected-motion.d.ts.map +0 -1
- package/dist/optics/aperture.d.ts.map +0 -1
- package/dist/optics/circle-of-confusion.d.ts.map +0 -1
- package/dist/optics/complex-pupil-psf.d.ts.map +0 -1
- package/dist/optics/depth-of-field.d.ts.map +0 -1
- package/dist/optics/diffraction.d.ts.map +0 -1
- package/dist/optics/focus-breathing.d.ts.map +0 -1
- package/dist/optics/focus-state.d.ts.map +0 -1
- package/dist/optics/front-of-lens-filter.d.ts.map +0 -1
- package/dist/optics/illumination-vignetting.d.ts.map +0 -1
- package/dist/optics/lateral-chromatic-aberration.d.ts.map +0 -1
- package/dist/optics/lens-psf-profile.d.ts.map +0 -1
- package/dist/optics/polygon-diffraction.d.ts.map +0 -1
- package/dist/optics/profile-contract.d.ts.map +0 -1
- package/dist/optics/psf-foundation.d.ts.map +0 -1
- package/dist/optics/radial-distortion.d.ts.map +0 -1
- package/dist/optics/scene-to-sensor-irradiance.d.ts.map +0 -1
- package/dist/optics/scene-to-sensor-quadrature.d.ts.map +0 -1
- package/dist/optics/sensor-aperture-rays.d.ts.map +0 -1
- package/dist/optics/sensor-environment-query.d.ts.map +0 -1
- package/dist/optics/sensor-psf-quadrature.d.ts.map +0 -1
- package/dist/optics/sensor-psf-support.d.ts.map +0 -1
- package/dist/optics/stray-light.d.ts.map +0 -1
- package/dist/optics/thin-lens.d.ts.map +0 -1
- package/dist/output/capture-corrected-sdr.d.ts.map +0 -1
- package/dist/output/capture-geometry.d.ts.map +0 -1
- package/dist/output/capture-sdr.d.ts.map +0 -1
- package/dist/output/crop.d.ts.map +0 -1
- package/dist/output/geometric-transforms.d.ts.map +0 -1
- package/dist/output/lens-corrections.d.ts.map +0 -1
- package/dist/output/native-capture-sdr.d.ts.map +0 -1
- package/dist/output/print-contrast-reference.d.ts.map +0 -1
- package/dist/output/print-detail.d.ts.map +0 -1
- package/dist/output/print-jpeg.d.ts.map +0 -1
- package/dist/output/print-plan.d.ts.map +0 -1
- package/dist/output/print-region-statistics.d.ts.map +0 -1
- package/dist/output/sdr-rendering.d.ts.map +0 -1
- package/dist/output/subject-framing-crop.d.ts.map +0 -1
- package/dist/schema/camera.d.ts.map +0 -1
- package/dist/schema/camera.js +0 -3
- package/dist/schema/camera.js.map +0 -1
- package/dist/schema/illumination-spectral.d.ts.map +0 -1
- package/dist/schema/illumination-temporal.d.ts.map +0 -1
- package/dist/schema/illumination.d.ts.map +0 -1
- package/dist/schema/scene-radiance-temporal.d.ts.map +0 -1
- package/dist/schema/scene-radiance.d.ts.map +0 -1
- package/dist/schema/scene.d.ts.map +0 -1
- package/dist/schema/scene.js +0 -3
- package/dist/schema/scene.js.map +0 -1
- package/dist/schema/validation.d.ts.map +0 -1
- package/dist/sensor/accumulated-charge.d.ts.map +0 -1
- package/dist/sensor/architecture.d.ts.map +0 -1
- package/dist/sensor/camera-saturation-capacity.d.ts.map +0 -1
- package/dist/sensor/capture-color-sampling-binding.d.ts.map +0 -1
- package/dist/sensor/capture-mode-timing.d.ts.map +0 -1
- package/dist/sensor/capture-mode.d.ts.map +0 -1
- package/dist/sensor/color-sampling.d.ts.map +0 -1
- package/dist/sensor/constant-rate-temporal-integration.d.ts.map +0 -1
- package/dist/sensor/dark-current.d.ts.map +0 -1
- package/dist/sensor/environment-photo-signal.d.ts.map +0 -1
- package/dist/sensor/eqe-electron-rate.d.ts.map +0 -1
- package/dist/sensor/eqe-local-exposure.d.ts.map +0 -1
- package/dist/sensor/eqe-temporal-exposure.d.ts.map +0 -1
- package/dist/sensor/exposure-window.d.ts.map +0 -1
- package/dist/sensor/iso-signal-chain.d.ts.map +0 -1
- package/dist/sensor/local-exposure-binding.d.ts.map +0 -1
- package/dist/sensor/optical-stack.d.ts.map +0 -1
- package/dist/sensor/photon-energy.d.ts.map +0 -1
- package/dist/sensor/physical-charge-capacity.d.ts.map +0 -1
- package/dist/sensor/pixel-pitch.d.ts.map +0 -1
- package/dist/sensor/radiometry-readiness.d.ts.map +0 -1
- package/dist/sensor/raw-readout.d.ts.map +0 -1
- package/dist/sensor/raw-reconstruction.d.ts.map +0 -1
- package/dist/sensor/readout-exposure-linkage.d.ts.map +0 -1
- package/dist/sensor/readout-timing.d.ts.map +0 -1
- package/dist/sensor/response-application-compatibility.d.ts.map +0 -1
- package/dist/sensor/response-operating-range.d.ts.map +0 -1
- package/dist/sensor/responsivity-photocurrent.d.ts.map +0 -1
- package/dist/sensor/sampling-aperture.d.ts.map +0 -1
- package/dist/sensor/scene-eqe-temporal-exposure.d.ts.map +0 -1
- package/dist/sensor/sensor-geometry.d.ts.map +0 -1
- package/dist/sensor/signal-noise.d.ts.map +0 -1
- package/dist/sensor/spatial-sample-reduction.d.ts.map +0 -1
- package/dist/sensor/spatial-sampling-quadrature.d.ts.map +0 -1
- package/dist/sensor/spatio-spectral-reduction.d.ts.map +0 -1
- package/dist/sensor/spectral-coverage.d.ts.map +0 -1
- package/dist/sensor/spectral-quadrature.d.ts.map +0 -1
- package/dist/sensor/spectral-response.d.ts.map +0 -1
- package/dist/sensor/temporal-eqe-sum.d.ts.map +0 -1
- package/dist/sensor/temporal-photo-signal.d.ts.map +0 -1
- package/dist/sensor/temporal-sample-binding.d.ts.map +0 -1
- package/dist/simulation/poc-simulation.d.ts.map +0 -1
- package/dist/stabilization/camera-shake.d.ts.map +0 -1
- package/dist/stabilization/system.d.ts.map +0 -1
- package/docs/API_STYLE.md +0 -235
- package/docs/ARCHITECTURE.md +0 -356
- package/docs/AUTOMATION_COORDINATION.md +0 -190
- package/docs/CAPTURE_COLOR.md +0 -25
- package/docs/CAPTURE_CORRECTED_SDR.md +0 -25
- package/docs/CAPTURE_EXPORT_METADATA.md +0 -27
- package/docs/CAPTURE_SDR.md +0 -22
- package/docs/DEVELOPERS.md +0 -68
- package/docs/DIGITAL_OPTICS_FOUNDATION.md +0 -69
- package/docs/ENVIRONMENT_RAW_CAPTURE.md +0 -208
- package/docs/EXPORT_ACCEPTANCE.md +0 -133
- package/docs/GENERIC_TIER_PRESETS.md +0 -269
- package/docs/GEOMETRIC_PREPARATION_REUSE.md +0 -141
- package/docs/IMAGE_FORMATION.md +0 -247
- package/docs/LINEAR_CAPTURE_ENCODING.md +0 -25
- package/docs/MOTION_AND_SIGNAL.md +0 -250
- package/docs/NATIVE_CAPTURE_SDR.md +0 -70
- package/docs/NATIVE_CAPTURE_SDR_REVIEW.md +0 -37
- package/docs/NATIVE_CAPTURE_SDR_VALIDATION.md +0 -34
- package/docs/NATIVE_RAW_AND_PRINT.md +0 -47
- package/docs/NUMERICAL_CORRECTNESS.md +0 -191
- package/docs/PERFORMANCE_BASELINE.md +0 -56
- package/docs/PHOTOGRAPHIC_EXPORT.md +0 -206
- package/docs/PHYSICS_FOUNDATION.md +0 -426
- package/docs/POC_API.md +0 -278
- package/docs/POC_PROJECTION_PLATFORM_REFERENCE.md +0 -12
- package/docs/POC_PROJECTION_REUSE.md +0 -124
- package/docs/PRINT_195_196_REVIEW.md +0 -93
- package/docs/PRINT_196_ENGINE_ACCEPTANCE.md +0 -45
- package/docs/PRINT_CONTRAST_REFERENCE.md +0 -43
- package/docs/PRINT_DETAIL_ASSESSMENT.md +0 -81
- package/docs/PRINT_DETAIL_JPEG_EVIDENCE.md +0 -36
- package/docs/PRINT_DETAIL_SDR_EVIDENCE.md +0 -29
- package/docs/PRINT_DETAIL_VALIDATION.md +0 -36
- package/docs/PRINT_PLANNING.md +0 -75
- package/docs/PRINT_REGION_STATISTICS.md +0 -38
- package/docs/PROCESSED_OUTPUT.md +0 -157
- package/docs/PRODUCTION_COMPOSITION.md +0 -373
- package/docs/PRODUCTION_ENVIRONMENT_CAPTURE.md +0 -131
- package/docs/PROVENANCE.md +0 -115
- package/docs/PSF_FOUNDATION.md +0 -165
- package/docs/RAW_FRAME_ENVELOPE.md +0 -56
- package/docs/RAW_FRAME_RECONSTRUCTION.md +0 -30
- package/docs/RELEASE_1_0.md +0 -66
- package/docs/RELEASE_1_0_1.md +0 -61
- package/docs/RELEASE_1_1_0.md +0 -25
- package/docs/RELEASE_1_2_0.md +0 -51
- package/docs/RELEASE_1_3_0.md +0 -15
- package/docs/RELEASE_1_4_0.md +0 -23
- package/docs/RELEASE_AUDIT.md +0 -39
- package/docs/SCENE_RADIANCE_AND_ILLUMINATION.md +0 -298
- package/docs/SCENE_SENSOR_QUADRATURE.md +0 -98
- package/docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md +0 -86
- package/docs/SCIENTIFIC_ASSURANCE.md +0 -280
- package/docs/SCIENTIFIC_CONFORMANCE.md +0 -83
- package/docs/SDR_RENDERING.md +0 -33
- package/docs/SENSOR_APERTURE_RAYS.md +0 -23
- package/docs/SENSOR_ENVIRONMENT_QUERY.md +0 -86
- package/docs/SENSOR_EQE_LOCAL_EXPOSURE.md +0 -104
- package/docs/SENSOR_EQE_TEMPORAL_EXPOSURE.md +0 -74
- package/docs/SENSOR_PSF_QUADRATURE.md +0 -90
- package/docs/SENSOR_RAW_FRAME.md +0 -20
- package/docs/SENSOR_RAW_PRODUCER.md +0 -77
- package/docs/SIGNAL_CONFORMANCE.md +0 -23
- package/docs/SIMULATED_CAPTURE.md +0 -65
- package/docs/STABILIZATION.md +0 -234
- package/docs/TEMPORAL_PHOTO_RAW.md +0 -83
- package/docs/TIER_ACCEPTANCE.md +0 -129
- package/docs/TIER_PRESET_ACCEPTANCE.md +0 -59
- package/docs/V1_COMPOSITION_MAP.md +0 -123
- package/docs/V1_HELPER_REUSE_REVIEW.md +0 -60
- package/docs/V1_PERFORMANCE_DISPOSITION.md +0 -88
- package/docs/benchmarks/2026-10-01-main-baseline.json +0 -694
- package/docs/benchmarks/2026-10-02-geometric-preparation-reuse.json +0 -2190
- package/docs/benchmarks/2026-10-02-poc-projection-reuse.json +0 -2423
- package/docs/benchmarks/2026-10-02-v1-environment-gc-profile.json +0 -210
- package/docs/benchmarks/2026-10-02-v1-environment-ordinary.json +0 -187
- package/docs/benchmarks/2026-10-02-v1-geometry-gc-profile.json +0 -756
- package/docs/benchmarks/2026-10-02-v1-geometry-ordinary-1.json +0 -711
- package/docs/benchmarks/2026-10-02-v1-geometry-ordinary-2.json +0 -711
- package/docs/benchmarks/2026-10-02-v1-poc-gc-profile.json +0 -885
- package/docs/benchmarks/2026-10-02-v1-poc-ordinary-1.json +0 -868
- package/docs/benchmarks/2026-10-02-v1-poc-ordinary-2.json +0 -868
- package/docs/licenses/castleCSF-MIT.txt +0 -21
- package/docs/validation/documentation-fragments.json +0 -212
- package/docs/validation/native-capture-sdr-darwin-arm64-node26-review.jsonl +0 -4
- package/docs/validation/native-capture-sdr-darwin-arm64.jsonl +0 -3
- package/docs/validation/native-raw-print-2026-10-04/fractional-asymmetric-crop.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/gray-ramp.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/linear-area-checker.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/manifest.json +0 -218
- package/docs/validation/native-raw-print-2026-10-04/megapixel-native.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/native-color.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel-validation.json +0 -9
- package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json +0 -29
- package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json.codes.u16le.gz +0 -0
- package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json.rgb.gz +0 -0
- package/docs/validation/native-raw-print-2026-10-04/srgb.icc +0 -0
- package/docs/validation/native-raw-print-2026-10-04/validation.json +0 -41
- package/docs/validation/print-196-candidate-capabilities.json +0 -28
- package/docs/validation/print-196-candidate-evidence.json +0 -356
- package/docs/validation/print-196-engine-acceptance.json +0 -81
- package/docs/validation/print-detail-capabilities.json +0 -103
- package/docs/validation/print-detail-jpeg-evidence.json +0 -116
- package/docs/validation/print-detail-sdr-evidence.json +0 -81
- package/docs/validation/release-audit-inventory.json +0 -1306
- package/docs/validation/tier-acceptance-report-v1.json +0 -2538
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"longitudinal-chromatic-aberration.js","sourceRoot":"","sources":["../../src/optics/longitudinal-chromatic-aberration.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Longitudinal (axial) chromatic aberration: wavelength-dependent focal length and the resulting\n * per-wavelength image-plane defocus for a sensor focused at a reference wavelength.\n *\n * Two dispersion inputs:\n * - thin-singlet-abbe: an ideal thin singlet whose index follows a two-term Cauchy dispersion\n * n(lambda) = A + B / lambda^2 fitted to n_d and the Abbe number V_d = (n_d - 1) / (n_F - n_C)\n * (Cauchy 1836; Oh 2023, arXiv:2309.09375, sec. 2.3.1(b), free; Abbe number: Greivenkamp,\n * OPTI-502 course notes, University of Arizona, sec. 17, free. Also see: Born & Wolf, Principles\n * of Optics, sec. 2.3; Hecht, Optics, 5th ed., sec. 3.5 and 6.3). Lensmaker scaling gives\n * f(lambda) = f_ref (n_ref - 1) / (n(lambda) - 1), so f_C - f_F ~ f_d / V_d (Greivenkamp,\n * OPTI-502 course notes, sec. 20, free. Also see: Hecht sec. 6.3.2; Kingslake & Johnson, Lens\n * Design Fundamentals, 2nd ed., ch. 5). The Fraunhofer d, F and C wavelengths (587.5618, 486.1327, 656.2725 nm) are standard\n * spectral-line constants (SCHOTT Technical Information TIE-29, 2023, free; also specified in\n * ISO 7944). A real multi-element lens is not a singlet, so this is an educational\n * approximation.\n * - declared-focal-shift: a caller-supplied table of focal-length shift versus wavelength\n * (for example a corrected lens's secondary spectrum), interpolated linearly without extrapolation.\n *\n * How defocus is computed:\n * - The sensor sits at the Gaussian thin-lens image distance for focusDistanceM at the reference\n * wavelength.\n * - At each wavelength, the image distance of subjectDistanceM uses f(lambda).\n * - The signed image-plane defocus dz is the sensor distance minus that image distance.\n * - The geometric blur diameter is D |dz| / v(lambda), where D = f_ref / N is the entrance-pupil\n * diameter. This is the same thin-lens form as calculateDefocusCircle().\n * The defocus also feeds calculateDefocusWavefront(), so a complex-pupil PSF (point-spread function)\n * can be evaluated per wavelength.\n * @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport {\n approximationResult,\n type CalculationResult\n} from \"../core/calculation-result.js\";\nimport {\n InvalidScientificInputError,\n requirePositiveFinite\n} from \"../core/validation.js\";\nimport { calculateDefocusWavefront } from \"./zernike-wavefront.js\";\nimport { requireInputKeys } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\n\n/** Fraunhofer spectral-line wavelengths in nm (SCHOTT TIE-29 table; also ISO 7944 reference wavelengths). */\nexport const FRAUNHOFER_D_LINE_NM = 587.5618;\nexport const FRAUNHOFER_F_LINE_NM = 486.1327;\nexport const FRAUNHOFER_C_LINE_NM = 656.2725;\n\nconst CAUCHY_MINIMUM_WAVELENGTH_NM = 360;\nconst CAUCHY_MAXIMUM_WAVELENGTH_NM = 830;\n\nexport type LongitudinalChromaticDispersion =\n | {\n kind: \"thin-singlet-abbe\";\n /** Refractive index at the d line. */\n refractiveIndexD: number;\n /** Abbe number V_d = (n_d - 1) / (n_F - n_C). */\n abbeNumberD: number;\n }\n | {\n kind: \"declared-focal-shift\";\n /** Strictly increasing wavelengths; shift is f(lambda) - f_nominal in micrometres. */\n samples: readonly {\n wavelengthNm: number;\n focalLengthShiftMicrometers: number;\n }[];\n };\n\nexport interface CalculateLongitudinalChromaticFocusInput {\n /** Focal length at the reference wavelength, in mm. */\n focalLengthMm: number;\n /** Wavelength at which the sensor is focused, in nm. */\n referenceWavelengthNm: number;\n /** Wavelength to evaluate, in nm (same wavelength basis as the dispersion data). */\n wavelengthNm: number;\n /** Nominal f-number at the reference wavelength (entrance-pupil diameter = f / N). */\n apertureFNumber: number;\n /** Focus (object) distance at the reference wavelength, metres from the principal plane. */\n focusDistanceM: number;\n /** Subject distance in metres; defaults to focusDistanceM. */\n subjectDistanceM?: number;\n dispersion: LongitudinalChromaticDispersion;\n}\n\nexport interface LongitudinalChromaticFocus {\n wavelengthNm: number;\n referenceWavelengthNm: number;\n focalLengthAtWavelengthMm: number;\n /** f(lambda) - f(reference), micrometres. */\n focalShiftMicrometers: number;\n /** Sensor plane distance (reference-wavelength image of the focus plane), mm. */\n sensorImageDistanceMm: number;\n /** Image distance of the subject at this wavelength, mm. */\n imageDistanceAtWavelengthMm: number;\n /** Sensor minus image distance, micrometres. */\n signedDefocusImagePlaneMicrometers: number;\n /** Geometric thin-lens blur-circle diameter at the sensor, mm. */\n geometricBlurDiameterMm: number;\n /** Image-side working f-number v(lambda) / D. */\n workingFNumberAtWavelength: number;\n /** Defocus wave aberration W020 for the complex-pupil PSF, micrometres. */\n w020Micrometers: number;\n /** Equivalent Noll Z4 coefficient, micrometres. */\n zernikeZ4Micrometers: number;\n}\n\nfunction requireFinite(name: string, value: unknown): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new InvalidScientificInputError(`${name} must be finite.`);\n }\n return value;\n}\n\nfunction cauchyIndex(\n refractiveIndexD: number,\n abbeNumberD: number,\n wavelengthNm: number\n): number {\n const inverseSquare = (nm: number): number => 1 / (nm / 1000) ** 2;\n const b =\n (refractiveIndexD - 1) /\n abbeNumberD /\n (inverseSquare(FRAUNHOFER_F_LINE_NM) - inverseSquare(FRAUNHOFER_C_LINE_NM));\n return (\n refractiveIndexD +\n b * (inverseSquare(wavelengthNm) - inverseSquare(FRAUNHOFER_D_LINE_NM))\n );\n}\n\n/**\n * Two-term Cauchy refractive index fitted to n_d and V_d. Valid as an approximation over\n * 360-830 nm only.\n */\nexport function calculateCauchyRefractiveIndex(input: {\n refractiveIndexD: number;\n abbeNumberD: number;\n wavelengthNm: number;\n}): CalculationResult<{ refractiveIndex: number }> {\n requireInputKeys(input, \"calculateCauchyRefractiveIndex\", [\"refractiveIndexD\", \"abbeNumberD\", \"wavelengthNm\"]);\n validateAbbe(input.refractiveIndexD, input.abbeNumberD);\n validateCauchyWavelength(\"wavelengthNm\", input.wavelengthNm);\n return approximationResult(\n {\n refractiveIndex: cauchyIndex(\n input.refractiveIndexD,\n input.abbeNumberD,\n input.wavelengthNm\n )\n },\n \"two-term-cauchy-abbe-dispersion\",\n \"1.0.0\",\n [\n \"n(lambda) = A + B / lambda^2 fitted exactly to n_d and V_d = (n_d - 1) / (n_F - n_C)\",\n \"Two-term Cauchy dispersion is an approximation for normal dispersion in the visible (360-830 nm)\"\n ]\n );\n}\n\nfunction validateAbbe(refractiveIndexD: unknown, abbeNumberD: unknown): void {\n const n = requireFinite(\"dispersion.refractiveIndexD\", refractiveIndexD);\n const v = requireFinite(\"dispersion.abbeNumberD\", abbeNumberD);\n if (n <= 1 || n > 4) {\n throw new InvalidScientificInputError(\n \"dispersion.refractiveIndexD must lie in (1, 4].\"\n );\n }\n if (v < 5 || v > 200) {\n throw new InvalidScientificInputError(\n \"dispersion.abbeNumberD must lie in [5, 200].\"\n );\n }\n}\n\nfunction validateCauchyWavelength(name: string, value: unknown): void {\n const wavelength = requireFinite(name, value);\n if (\n wavelength < CAUCHY_MINIMUM_WAVELENGTH_NM ||\n wavelength > CAUCHY_MAXIMUM_WAVELENGTH_NM\n ) {\n throw new InvalidScientificInputError(\n `${name} must lie in ${CAUCHY_MINIMUM_WAVELENGTH_NM}-${CAUCHY_MAXIMUM_WAVELENGTH_NM} nm for the Cauchy dispersion approximation.`\n );\n }\n}\n\nfunction interpolateShift(\n samples: readonly { wavelengthNm: number; focalLengthShiftMicrometers: number }[],\n wavelengthNm: number,\n name: string\n): number {\n const first = samples[0]!;\n const last = samples[samples.length - 1]!;\n if (wavelengthNm < first.wavelengthNm || wavelengthNm > last.wavelengthNm) {\n throw new InvalidScientificInputError(\n `${name} lies outside the declared focal-shift wavelength range; extrapolation is not performed.`\n );\n }\n for (let index = 1; index < samples.length; index += 1) {\n const right = samples[index]!;\n if (wavelengthNm <= right.wavelengthNm) {\n const left = samples[index - 1]!;\n const t = (wavelengthNm - left.wavelengthNm) / (right.wavelengthNm - left.wavelengthNm);\n return (\n left.focalLengthShiftMicrometers +\n t * (right.focalLengthShiftMicrometers - left.focalLengthShiftMicrometers)\n );\n }\n }\n return first.focalLengthShiftMicrometers;\n}\n\nfunction parseSamples(\n value: unknown\n): readonly { wavelengthNm: number; focalLengthShiftMicrometers: number }[] {\n if (!Array.isArray(value) || value.length < 2 || value.length > 1024) {\n throw new InvalidScientificInputError(\n \"dispersion.samples must contain 2 through 1024 entries.\"\n );\n }\n let previous = 0;\n return value.map((entry: unknown, index) => {\n if (typeof entry !== \"object\" || entry === null) {\n throw new InvalidConfigurationError(`dispersion.samples[${index}] must be an object.`);\n }\n const record = entry as Record<string, unknown>;\n const wavelengthNm = requireFinite(`dispersion.samples[${index}].wavelengthNm`, record.wavelengthNm);\n if (wavelengthNm <= previous) {\n throw new InvalidScientificInputError(\n \"dispersion.samples wavelengths must be positive and strictly increasing.\"\n );\n }\n previous = wavelengthNm;\n return {\n wavelengthNm,\n focalLengthShiftMicrometers: requireFinite(\n `dispersion.samples[${index}].focalLengthShiftMicrometers`,\n record.focalLengthShiftMicrometers\n )\n };\n });\n}\n\nfunction imageDistanceMm(focalLengthMm: number, objectDistanceM: number): number {\n const objectMm = objectDistanceM * 1000;\n if (objectMm <= focalLengthMm) {\n throw new InvalidScientificInputError(\n \"Object distances must lie beyond the wavelength-dependent focal length.\"\n );\n }\n return (focalLengthMm * objectMm) / (objectMm - focalLengthMm);\n}\n\n/**\n * Wavelength-dependent focus for one wavelength: focal length, image distance, signed defocus at\n * a sensor focused at the reference wavelength, geometric blur and the defocus wavefront.\n */\nexport function calculateLongitudinalChromaticFocus(\n input: CalculateLongitudinalChromaticFocusInput\n): CalculationResult<LongitudinalChromaticFocus> {\n requireInputKeys(input, \"calculateLongitudinalChromaticFocus\", [\"focalLengthMm\", \"referenceWavelengthNm\", \"wavelengthNm\", \"apertureFNumber\", \"focusDistanceM\", \"subjectDistanceM\", \"dispersion\"]);\n requirePositiveFinite(\"focalLengthMm\", input.focalLengthMm);\n requirePositiveFinite(\"referenceWavelengthNm\", input.referenceWavelengthNm);\n requirePositiveFinite(\"wavelengthNm\", input.wavelengthNm);\n requirePositiveFinite(\"apertureFNumber\", input.apertureFNumber);\n requirePositiveFinite(\"focusDistanceM\", input.focusDistanceM);\n const subjectDistanceM = input.subjectDistanceM ?? input.focusDistanceM;\n requirePositiveFinite(\"subjectDistanceM\", subjectDistanceM);\n const dispersion = input.dispersion;\n if (typeof dispersion !== \"object\" || dispersion === null) {\n throw new InvalidConfigurationError(\"dispersion must be an object.\");\n }\n\n let focalLengthAtWavelengthMm: number;\n let model: string;\n let dispersionAssumption: string;\n if (dispersion.kind === \"thin-singlet-abbe\") {\n validateAbbe(dispersion.refractiveIndexD, dispersion.abbeNumberD);\n validateCauchyWavelength(\"referenceWavelengthNm\", input.referenceWavelengthNm);\n validateCauchyWavelength(\"wavelengthNm\", input.wavelengthNm);\n const nRef = cauchyIndex(dispersion.refractiveIndexD, dispersion.abbeNumberD, input.referenceWavelengthNm);\n const nLambda = cauchyIndex(dispersion.refractiveIndexD, dispersion.abbeNumberD, input.wavelengthNm);\n focalLengthAtWavelengthMm = (input.focalLengthMm * (nRef - 1)) / (nLambda - 1);\n model = \"thin-singlet-abbe-longitudinal-chromatic-focus\";\n dispersionAssumption =\n \"Ideal thin singlet with two-term Cauchy dispersion fitted to n_d and V_d; f(lambda) = f_ref (n_ref - 1) / (n(lambda) - 1)\";\n } else if (dispersion.kind === \"declared-focal-shift\") {\n const samples = parseSamples(dispersion.samples);\n const shiftRef = interpolateShift(samples, input.referenceWavelengthNm, \"referenceWavelengthNm\");\n const shift = interpolateShift(samples, input.wavelengthNm, \"wavelengthNm\");\n focalLengthAtWavelengthMm = input.focalLengthMm + (shift - shiftRef) / 1000;\n model = \"declared-focal-shift-longitudinal-chromatic-focus\";\n dispersionAssumption =\n \"Caller-declared focal-length shift table, linearly interpolated and re-referenced to the reference wavelength; no extrapolation\";\n } else {\n throw new InvalidConfigurationError(\"dispersion.kind is invalid.\");\n }\n if (!(focalLengthAtWavelengthMm > 0) || !Number.isFinite(focalLengthAtWavelengthMm)) {\n throw new InvalidScientificInputError(\n \"Wavelength-dependent focal length must remain finite and positive.\"\n );\n }\n\n const sensorImageDistanceMm = imageDistanceMm(input.focalLengthMm, input.focusDistanceM);\n const imageDistanceAtWavelengthMm = imageDistanceMm(focalLengthAtWavelengthMm, subjectDistanceM);\n const pupilDiameterMm = input.focalLengthMm / input.apertureFNumber;\n const defocusMm = sensorImageDistanceMm - imageDistanceAtWavelengthMm;\n const workingFNumberAtWavelength = imageDistanceAtWavelengthMm / pupilDiameterMm;\n const wavefront = calculateDefocusWavefront({\n signedDefocusImagePlaneMicrometers: defocusMm * 1000,\n workingFNumber: workingFNumberAtWavelength\n }).value;\n\n return approximationResult(\n {\n wavelengthNm: input.wavelengthNm,\n referenceWavelengthNm: input.referenceWavelengthNm,\n focalLengthAtWavelengthMm,\n focalShiftMicrometers: (focalLengthAtWavelengthMm - input.focalLengthMm) * 1000,\n sensorImageDistanceMm,\n imageDistanceAtWavelengthMm,\n signedDefocusImagePlaneMicrometers: defocusMm * 1000,\n geometricBlurDiameterMm:\n (pupilDiameterMm * Math.abs(defocusMm)) / imageDistanceAtWavelengthMm,\n workingFNumberAtWavelength,\n w020Micrometers: wavefront.w020Micrometers,\n zernikeZ4Micrometers: wavefront.zernikeZ4Micrometers\n },\n model,\n \"1.0.0\",\n [\n dispersionAssumption,\n \"Gaussian thin-lens imaging; the sensor is focused on focusDistanceM at the reference wavelength\",\n \"Entrance-pupil diameter f_ref / N is wavelength independent; distances are measured from ideal principal planes\",\n \"Longitudinal chromatic focus only: lateral chromatic magnification, spherochromatism and sensor response are separate\",\n \"Wavelength basis must match the dispersion data; no air/vacuum conversion is performed\"\n ]\n );\n}\n"]}
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
2
|
+
* Diffraction PSF (point-spread function) of a polygon-shaped aperture.
|
|
3
|
+
*
|
|
4
|
+
* The main model gives the continuous, single-wavelength Fraunhofer (far-field) PSF density of an
|
|
5
|
+
* ideal regular polygon with straight edges. The pupil is uniformly lit, has zero phase and sits on
|
|
6
|
+
* the optical axis.
|
|
7
|
+
* - The physical area is explicit. f/N may supply the diameter of a circle with the same area, but
|
|
8
|
+
* only when the caller declares the nominal-area convention.
|
|
9
|
+
* - Nothing else is assumed: no phase aberration, clipping, field dependence, curved blades, defocus
|
|
10
|
+
* or multi-wavelength behaviour.
|
|
11
|
+
*
|
|
12
|
+
* Density = A |F/A|² / (lambda * propagationDistance)². The density integrates to 1 over the
|
|
13
|
+
* infinite image plane (Parseval). It is NOT normalized over the supplied list of points. Code that
|
|
14
|
+
* sums these samples must keep density × area and report truncation and convergence.
|
|
15
|
+
* @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers
|
|
16
|
+
* and support limits.
|
|
12
17
|
*/
|
|
13
18
|
import { type CalculationResult } from "../core/calculation-result.js";
|
|
14
19
|
import { type CalculateIdealApertureInput } from "./aperture.js";
|
|
@@ -17,9 +22,9 @@ import type { SpectralWavelengthBasis } from "../core/spectral.js";
|
|
|
17
22
|
export interface CalculateIdealPolygonDiffractionInput extends CalculateIdealApertureInput {
|
|
18
23
|
/** Diameter of a circle with the SAME AREA as the physical polygon opening. */
|
|
19
24
|
equivalentAreaPupilDiameterMm: number;
|
|
20
|
-
/** Paraxial pupil
|
|
25
|
+
/** Paraxial propagation distance from pupil to image. Never inferred from focus. */
|
|
21
26
|
pupilToImageDistanceMm: number;
|
|
22
|
-
/** Wavelength in the declared propagation medium
|
|
27
|
+
/** Wavelength in the declared propagation medium. No air/vacuum conversion is applied. */
|
|
23
28
|
wavelengthNm: number;
|
|
24
29
|
wavelengthBasis: Exclude<SpectralWavelengthBasis, "unspecified">;
|
|
25
30
|
/** Displacements from the on-axis PSF center, +X right / +Y up; at most 4096. */
|
|
@@ -28,7 +33,7 @@ export interface CalculateIdealPolygonDiffractionInput extends CalculateIdealApe
|
|
|
28
33
|
y: number;
|
|
29
34
|
}[];
|
|
30
35
|
}
|
|
31
|
-
/**
|
|
36
|
+
/** Samples of a continuous unit-energy PSF. This is not a normalized finite convolution kernel. */
|
|
32
37
|
export interface IdealPolygonDiffraction {
|
|
33
38
|
bladeCount: number;
|
|
34
39
|
firstBladeEdgeAngleDegrees: number;
|
|
@@ -46,22 +51,74 @@ export interface IdealPolygonDiffraction {
|
|
|
46
51
|
x: number;
|
|
47
52
|
y: number;
|
|
48
53
|
};
|
|
49
|
-
/** |F/A
|
|
54
|
+
/** |F/A|². Equal to 1 at the origin. Not an energy or probability weight. */
|
|
50
55
|
peakNormalizedIntensity: number;
|
|
51
56
|
/** Density integrating to unity over the full image plane, in 1/µm². */
|
|
52
57
|
intensityDensityPerSquareMicrometer: number;
|
|
53
58
|
}[];
|
|
54
59
|
}
|
|
55
60
|
/**
|
|
56
|
-
* Calculates continuous
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
+
* Calculates the continuous, single-wavelength Fraunhofer (far-field) PSF
|
|
62
|
+
* density of an ideal regular polygon with straight edges. The pupil is
|
|
63
|
+
* uniformly lit, has zero phase and sits on the optical axis.
|
|
64
|
+
*
|
|
65
|
+
* The physical area is explicit. f/N may supply the equal-area diameter only
|
|
66
|
+
* when the caller declares the nominal-area convention. Nothing else is
|
|
67
|
+
* assumed: no phase aberration, clipping, field dependence, curved blades,
|
|
68
|
+
* defocus or multi-wavelength behaviour.
|
|
61
69
|
*
|
|
62
|
-
* Density = A |F/A|² / (lambda * propagationDistance)².
|
|
63
|
-
*
|
|
64
|
-
*
|
|
70
|
+
* Density = A |F/A|² / (lambda * propagationDistance)². It integrates to 1
|
|
71
|
+
* over the infinite plane (Parseval), NOT over the supplied points. Code that
|
|
72
|
+
* sums the samples must keep density × area and report truncation and
|
|
73
|
+
* convergence.
|
|
65
74
|
*/
|
|
66
75
|
export declare function calculateIdealPolygonDiffractionPsf(input: CalculateIdealPolygonDiffractionInput): CalculationResult<IdealPolygonDiffraction>;
|
|
67
|
-
|
|
76
|
+
/** On-axis scalar Fraunhofer diffraction of one arbitrary simple polygon pupil. */
|
|
77
|
+
export interface CalculatePolygonPupilFraunhoferPsfInput {
|
|
78
|
+
/**
|
|
79
|
+
* Simple (non-self-intersecting) pupil polygon in pupil-plane millimetres, +X right / +Y up,
|
|
80
|
+
* with 3 to 4096 vertices. For example, the cat's-eye pupil from calculateMechanicalVignetting().
|
|
81
|
+
*/
|
|
82
|
+
pupilVerticesMm: readonly {
|
|
83
|
+
x: number;
|
|
84
|
+
y: number;
|
|
85
|
+
}[];
|
|
86
|
+
/** Paraxial propagation distance from pupil to image. Never inferred from focus. */
|
|
87
|
+
pupilToImageDistanceMm: number;
|
|
88
|
+
/** Wavelength in the declared propagation medium. No air/vacuum conversion is applied. */
|
|
89
|
+
wavelengthNm: number;
|
|
90
|
+
wavelengthBasis: Exclude<SpectralWavelengthBasis, "unspecified">;
|
|
91
|
+
/** Displacements from the PSF centre (the geometric image point), +X right / +Y up; at most 4096. */
|
|
92
|
+
imagePointsMicrometers: readonly {
|
|
93
|
+
x: number;
|
|
94
|
+
y: number;
|
|
95
|
+
}[];
|
|
96
|
+
}
|
|
97
|
+
export interface PolygonPupilFraunhoferPsf {
|
|
98
|
+
pupilAreaSquareMm: number;
|
|
99
|
+
pupilToImageDistanceMm: number;
|
|
100
|
+
wavelengthNm: number;
|
|
101
|
+
wavelengthBasis: Exclude<SpectralWavelengthBasis, "unspecified">;
|
|
102
|
+
fieldAxes: "+X right, +Y up";
|
|
103
|
+
energyNormalization: "unit-integral-over-infinite-image-plane";
|
|
104
|
+
throughputApplied: false;
|
|
105
|
+
samples: readonly {
|
|
106
|
+
imagePointMicrometers: {
|
|
107
|
+
x: number;
|
|
108
|
+
y: number;
|
|
109
|
+
};
|
|
110
|
+
/** |F/A|²; unity at the origin. */
|
|
111
|
+
peakNormalizedIntensity: number;
|
|
112
|
+
/** Density integrating to unity over the full image plane, in 1/µm². */
|
|
113
|
+
intensityDensityPerSquareMicrometer: number;
|
|
114
|
+
}[];
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Continuous, single-wavelength Fraunhofer PSF density for any simple polygon pupil that is uniformly
|
|
118
|
+
* lit and has zero phase (for example a cat's-eye pupil from mechanical vignetting).
|
|
119
|
+
*
|
|
120
|
+
* It uses the same analytic edge integral as the regular-polygon model, so there is no aliasing from
|
|
121
|
+
* a pupil grid. Moving the pupil off the axis only adds a linear phase; the intensity does not
|
|
122
|
+
* change. Density = A |F/A|² / (lambda z)², and it integrates to 1 over the infinite plane.
|
|
123
|
+
*/
|
|
124
|
+
export declare function calculatePolygonPupilFraunhoferPsf(input: CalculatePolygonPupilFraunhoferPsfInput): CalculationResult<PolygonPupilFraunhoferPsf>;
|
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
3
|
+
* Diffraction PSF (point-spread function) of a polygon-shaped aperture.
|
|
4
|
+
*
|
|
5
|
+
* The main model gives the continuous, single-wavelength Fraunhofer (far-field) PSF density of an
|
|
6
|
+
* ideal regular polygon with straight edges. The pupil is uniformly lit, has zero phase and sits on
|
|
7
|
+
* the optical axis.
|
|
8
|
+
* - The physical area is explicit. f/N may supply the diameter of a circle with the same area, but
|
|
9
|
+
* only when the caller declares the nominal-area convention.
|
|
10
|
+
* - Nothing else is assumed: no phase aberration, clipping, field dependence, curved blades, defocus
|
|
11
|
+
* or multi-wavelength behaviour.
|
|
12
|
+
*
|
|
13
|
+
* Density = A |F/A|² / (lambda * propagationDistance)². The density integrates to 1 over the
|
|
14
|
+
* infinite image plane (Parseval). It is NOT normalized over the supplied list of points. Code that
|
|
15
|
+
* sums these samples must keep density × area and report truncation and convergence.
|
|
16
|
+
* @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers
|
|
17
|
+
* and support limits.
|
|
13
18
|
*/
|
|
14
19
|
import { approximationResult } from "../core/calculation-result.js";
|
|
15
20
|
import { InvalidScientificInputError, requirePositiveFinite } from "../core/validation.js";
|
|
16
21
|
import { calculateIdealApertureGeometry } from "./aperture.js";
|
|
22
|
+
import { requireInputKeys } from "../core/record-validation.js";
|
|
23
|
+
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
17
24
|
/** sin(x)/x - 1, evaluated without cancellation near zero. */
|
|
18
25
|
function sincMinusOne(x) {
|
|
19
26
|
if (Math.abs(x) < 0.01) {
|
|
@@ -23,10 +30,11 @@ function sincMinusOne(x) {
|
|
|
23
30
|
return Math.sin(x) / x - 1;
|
|
24
31
|
}
|
|
25
32
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
33
|
+
* Fourier transform of the polygon, written as an integral around its edges
|
|
34
|
+
* using the divergence theorem (independently derived). Coordinates use a
|
|
35
|
+
* circumradius of 1, so pupil size cannot affect numerical conditioning.
|
|
36
|
+
* Subtracting the zero-frequency edge term (which sums to zero around the
|
|
37
|
+
* closed polygon) avoids cancellation at and near the origin.
|
|
30
38
|
*/
|
|
31
39
|
function peakIntensity(vertices, area, qx, qy) {
|
|
32
40
|
const q = Math.hypot(qx, qy);
|
|
@@ -53,15 +61,19 @@ function peakIntensity(vertices, area, qx, qy) {
|
|
|
53
61
|
return real * real + imaginary * imaginary;
|
|
54
62
|
}
|
|
55
63
|
/**
|
|
56
|
-
* Calculates continuous
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
64
|
+
* Calculates the continuous, single-wavelength Fraunhofer (far-field) PSF
|
|
65
|
+
* density of an ideal regular polygon with straight edges. The pupil is
|
|
66
|
+
* uniformly lit, has zero phase and sits on the optical axis.
|
|
67
|
+
*
|
|
68
|
+
* The physical area is explicit. f/N may supply the equal-area diameter only
|
|
69
|
+
* when the caller declares the nominal-area convention. Nothing else is
|
|
70
|
+
* assumed: no phase aberration, clipping, field dependence, curved blades,
|
|
71
|
+
* defocus or multi-wavelength behaviour.
|
|
61
72
|
*
|
|
62
|
-
* Density = A |F/A|² / (lambda * propagationDistance)².
|
|
63
|
-
*
|
|
64
|
-
*
|
|
73
|
+
* Density = A |F/A|² / (lambda * propagationDistance)². It integrates to 1
|
|
74
|
+
* over the infinite plane (Parseval), NOT over the supplied points. Code that
|
|
75
|
+
* sums the samples must keep density × area and report truncation and
|
|
76
|
+
* convergence.
|
|
65
77
|
*/
|
|
66
78
|
export function calculateIdealPolygonDiffractionPsf(input) {
|
|
67
79
|
// Reject unmodeled effects rather than silently accepting and ignoring them.
|
|
@@ -71,13 +83,13 @@ export function calculateIdealPolygonDiffractionPsf(input) {
|
|
|
71
83
|
]);
|
|
72
84
|
if (typeof input !== "object" || input === null || Array.isArray(input) ||
|
|
73
85
|
Object.keys(input).some((key) => !allowed.has(key))) {
|
|
74
|
-
throw new
|
|
86
|
+
throw new InvalidConfigurationError("Polygon diffraction input contains unsupported fields or is not an object.");
|
|
75
87
|
}
|
|
76
88
|
requirePositiveFinite("equivalentAreaPupilDiameterMm", input.equivalentAreaPupilDiameterMm);
|
|
77
89
|
requirePositiveFinite("pupilToImageDistanceMm", input.pupilToImageDistanceMm);
|
|
78
90
|
requirePositiveFinite("wavelengthNm", input.wavelengthNm);
|
|
79
91
|
if (input.wavelengthBasis !== "air" && input.wavelengthBasis !== "vacuum") {
|
|
80
|
-
throw new
|
|
92
|
+
throw new InvalidConfigurationError("wavelengthBasis must be air or vacuum.");
|
|
81
93
|
}
|
|
82
94
|
if (input.firstBladeEdgeAngleDegrees !== undefined && !Number.isFinite(input.firstBladeEdgeAngleDegrees)) {
|
|
83
95
|
throw new InvalidScientificInputError("firstBladeEdgeAngleDegrees must be finite when supplied.");
|
|
@@ -91,7 +103,7 @@ export function calculateIdealPolygonDiffractionPsf(input) {
|
|
|
91
103
|
throw new InvalidScientificInputError("imagePointsMicrometers must not contain sparse entries.");
|
|
92
104
|
}
|
|
93
105
|
}
|
|
94
|
-
const geometry = calculateIdealApertureGeometry(input).value;
|
|
106
|
+
const geometry = calculateIdealApertureGeometry({ bladeCount: input.bladeCount, ...(input.firstBladeEdgeAngleDegrees === undefined ? {} : { firstBladeEdgeAngleDegrees: input.firstBladeEdgeAngleDegrees }) }).value;
|
|
95
107
|
const unitArea = input.bladeCount * Math.sin(2 * Math.PI / input.bladeCount) / 2;
|
|
96
108
|
const pupilAreaSquareMm = Math.PI * (input.equivalentAreaPupilDiameterMm / 2) ** 2;
|
|
97
109
|
const radius = Math.sqrt(pupilAreaSquareMm / unitArea);
|
|
@@ -142,4 +154,97 @@ export function calculateIdealPolygonDiffractionPsf(input) {
|
|
|
142
154
|
"Circular Airy remains a separate named diagnostic; do not stack this diffraction PSF over an already diffracted complex-pupil result."
|
|
143
155
|
], { notes: ["No quantified physical-model uncertainty is asserted. Numerical tolerances in tests are validation evidence, not real-lens accuracy bounds."] });
|
|
144
156
|
}
|
|
157
|
+
function requirePlanarPoint(value, path) {
|
|
158
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
159
|
+
throw new InvalidScientificInputError(`${path} must contain finite x/y coordinates only.`);
|
|
160
|
+
}
|
|
161
|
+
const record = value;
|
|
162
|
+
if (Object.keys(record).some((key) => key !== "x" && key !== "y") ||
|
|
163
|
+
typeof record.x !== "number" || typeof record.y !== "number" ||
|
|
164
|
+
!Number.isFinite(record.x) || !Number.isFinite(record.y)) {
|
|
165
|
+
throw new InvalidScientificInputError(`${path} must contain finite x/y coordinates only.`);
|
|
166
|
+
}
|
|
167
|
+
return { x: record.x, y: record.y };
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Continuous, single-wavelength Fraunhofer PSF density for any simple polygon pupil that is uniformly
|
|
171
|
+
* lit and has zero phase (for example a cat's-eye pupil from mechanical vignetting).
|
|
172
|
+
*
|
|
173
|
+
* It uses the same analytic edge integral as the regular-polygon model, so there is no aliasing from
|
|
174
|
+
* a pupil grid. Moving the pupil off the axis only adds a linear phase; the intensity does not
|
|
175
|
+
* change. Density = A |F/A|² / (lambda z)², and it integrates to 1 over the infinite plane.
|
|
176
|
+
*/
|
|
177
|
+
export function calculatePolygonPupilFraunhoferPsf(input) {
|
|
178
|
+
requireInputKeys(input, "calculatePolygonPupilFraunhoferPsf", ["pupilVerticesMm", "pupilToImageDistanceMm", "wavelengthNm", "wavelengthBasis", "imagePointsMicrometers"]);
|
|
179
|
+
requirePositiveFinite("pupilToImageDistanceMm", input.pupilToImageDistanceMm);
|
|
180
|
+
requirePositiveFinite("wavelengthNm", input.wavelengthNm);
|
|
181
|
+
if (input.wavelengthBasis !== "air" && input.wavelengthBasis !== "vacuum") {
|
|
182
|
+
throw new InvalidConfigurationError("wavelengthBasis must be air or vacuum.");
|
|
183
|
+
}
|
|
184
|
+
if (!Array.isArray(input.pupilVerticesMm) || input.pupilVerticesMm.length < 3 ||
|
|
185
|
+
input.pupilVerticesMm.length > 4096) {
|
|
186
|
+
throw new InvalidScientificInputError("pupilVerticesMm must contain 3 through 4096 vertices.");
|
|
187
|
+
}
|
|
188
|
+
if (!Array.isArray(input.imagePointsMicrometers) ||
|
|
189
|
+
input.imagePointsMicrometers.length === 0 || input.imagePointsMicrometers.length > 4096) {
|
|
190
|
+
throw new InvalidScientificInputError("imagePointsMicrometers must contain 1 through 4096 points.");
|
|
191
|
+
}
|
|
192
|
+
const vertices = input.pupilVerticesMm.map((vertex, index) => requirePlanarPoint(vertex, `pupilVerticesMm[${index}]`));
|
|
193
|
+
// Centre and scale the polygon for conditioning; translation changes only the phase of F.
|
|
194
|
+
const cx = vertices.reduce((sum, v) => sum + v.x, 0) / vertices.length;
|
|
195
|
+
const cy = vertices.reduce((sum, v) => sum + v.y, 0) / vertices.length;
|
|
196
|
+
const scale = Math.max(...vertices.map((v) => Math.hypot(v.x - cx, v.y - cy)));
|
|
197
|
+
if (!(scale > 0) || !Number.isFinite(scale)) {
|
|
198
|
+
throw new InvalidScientificInputError("pupilVerticesMm must span a finite non-zero region.");
|
|
199
|
+
}
|
|
200
|
+
let normalized = vertices.map((v) => ({ x: (v.x - cx) / scale, y: (v.y - cy) / scale }));
|
|
201
|
+
let twiceArea = 0;
|
|
202
|
+
for (let index = 0; index < normalized.length; index += 1) {
|
|
203
|
+
const a = normalized[index];
|
|
204
|
+
const b = normalized[(index + 1) % normalized.length];
|
|
205
|
+
twiceArea += a.x * b.y - b.x * a.y;
|
|
206
|
+
}
|
|
207
|
+
if (twiceArea < 0) {
|
|
208
|
+
normalized = [...normalized].reverse();
|
|
209
|
+
twiceArea = -twiceArea;
|
|
210
|
+
}
|
|
211
|
+
const unitArea = twiceArea / 2;
|
|
212
|
+
const pupilAreaSquareMm = unitArea * scale * scale;
|
|
213
|
+
const propagationScale = input.wavelengthNm / 1_000_000 * input.pupilToImageDistanceMm;
|
|
214
|
+
const densityScale = pupilAreaSquareMm / propagationScale ** 2 / 1_000_000;
|
|
215
|
+
if (!(unitArea > 1e-12) ||
|
|
216
|
+
![pupilAreaSquareMm, propagationScale, densityScale].every((x) => Number.isFinite(x) && x > 0)) {
|
|
217
|
+
throw new InvalidScientificInputError("Polygon pupil area and derived scales must remain finite and positive.");
|
|
218
|
+
}
|
|
219
|
+
const samples = input.imagePointsMicrometers.map((value, index) => {
|
|
220
|
+
const point = requirePlanarPoint(value, `imagePointsMicrometers[${index}]`);
|
|
221
|
+
const qx = 2 * Math.PI * (point.x / 1000) * scale / propagationScale;
|
|
222
|
+
const qy = 2 * Math.PI * (point.y / 1000) * scale / propagationScale;
|
|
223
|
+
if (!Number.isFinite(Math.hypot(qx, qy)) || Math.hypot(qx, qy) > 1_000_000) {
|
|
224
|
+
throw new InvalidScientificInputError("Dimensionless pupil phase radius must not exceed 1000000.");
|
|
225
|
+
}
|
|
226
|
+
const intensity = peakIntensity(normalized, unitArea, qx, qy);
|
|
227
|
+
return {
|
|
228
|
+
imagePointMicrometers: { x: point.x === 0 ? 0 : point.x, y: point.y === 0 ? 0 : point.y },
|
|
229
|
+
peakNormalizedIntensity: intensity,
|
|
230
|
+
intensityDensityPerSquareMicrometer: intensity * densityScale
|
|
231
|
+
};
|
|
232
|
+
});
|
|
233
|
+
return approximationResult({
|
|
234
|
+
pupilAreaSquareMm,
|
|
235
|
+
pupilToImageDistanceMm: input.pupilToImageDistanceMm,
|
|
236
|
+
wavelengthNm: input.wavelengthNm,
|
|
237
|
+
wavelengthBasis: input.wavelengthBasis,
|
|
238
|
+
fieldAxes: "+X right, +Y up",
|
|
239
|
+
energyNormalization: "unit-integral-over-infinite-image-plane",
|
|
240
|
+
throughputApplied: false,
|
|
241
|
+
samples
|
|
242
|
+
}, "polygon-pupil-fraunhofer-diffraction", "1.0.0", [
|
|
243
|
+
"Uniform unit pupil amplitude and zero phase over a caller-declared simple polygon; scalar paraxial Fraunhofer propagation.",
|
|
244
|
+
"The PSF is centred on the geometric image point; a pupil offset from the optical axis adds only a linear phase.",
|
|
245
|
+
"Continuous PSF density has unit integral over the infinite image plane. Point samples are not a finite energy-normalized kernel.",
|
|
246
|
+
"Pupil-area throughput (for example mechanical vignetting) is reported separately and not applied to the density.",
|
|
247
|
+
"No aberration, defocus, polarization, sensor response or stray light is modeled."
|
|
248
|
+
], { notes: ["No quantified physical-model uncertainty is asserted. Numerical tolerances in tests are validation evidence, not real-lens accuracy bounds."] });
|
|
249
|
+
}
|
|
145
250
|
//# sourceMappingURL=polygon-diffraction.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"polygon-diffraction.js","sourceRoot":"","sources":["../../src/optics/polygon-diffraction.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,mBAAmB,EAA0B,MAAM,+BAA+B,CAAC;AAC5F,OAAO,EAAE,2BAA2B,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAAE,8BAA8B,EAAoC,MAAM,eAAe,CAAC;AAsCjG,8DAA8D;AAC9D,SAAS,YAAY,CAAC,CAAS;IAC7B,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;QACjB,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;GAKG;AACH,SAAS,aAAa,CACpB,QAA6C,EAC7C,IAAY,EACZ,EAAU,EACV,EAAU;IAEV,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAC7B,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACtB,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAClB,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAClB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACxD,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAE,CAAC;QACnD,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACrB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACrB,MAAM,aAAa,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAClE,MAAM,SAAS,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC;QACrB,MAAM,WAAW,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;QAC/C,qEAAqE;QACrE,IAAI,IAAI,WAAW,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3D,SAAS,IAAI,WAAW,GAAG,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACrF,CAAC;IACD,OAAO,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mCAAmC,CACjD,KAA4C;IAE5C,6EAA6E;IAC7E,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC;QACtB,YAAY,EAAE,4BAA4B,EAAE,+BAA+B;QAC3E,wBAAwB,EAAE,cAAc,EAAE,iBAAiB,EAAE,wBAAwB;KACtF,CAAC,CAAC;IACH,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACnE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,2BAA2B,CAAC,4EAA4E,CAAC,CAAC;IACtH,CAAC;IACD,qBAAqB,CAAC,+BAA+B,EAAE,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC5F,qBAAqB,CAAC,wBAAwB,EAAE,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC9E,qBAAqB,CAAC,cAAc,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAC1D,IAAI,KAAK,CAAC,eAAe,KAAK,KAAK,IAAI,KAAK,CAAC,eAAe,KAAK,QAAQ,EAAE,CAAC;QAC1E,MAAM,IAAI,2BAA2B,CAAC,wCAAwC,CAAC,CAAC;IAClF,CAAC;IACD,IAAI,KAAK,CAAC,0BAA0B,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,0BAA0B,CAAC,EAAE,CAAC;QACzG,MAAM,IAAI,2BAA2B,CAAC,0DAA0D,CAAC,CAAC;IACpG,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC;QAC5C,KAAK,CAAC,sBAAsB,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,sBAAsB,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QAC5F,MAAM,IAAI,2BAA2B,CAAC,4DAA4D,CAAC,CAAC;IACtG,CAAC;IACD,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,sBAAsB,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC5E,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,2BAA2B,CAAC,yDAAyD,CAAC,CAAC;QACnG,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,8BAA8B,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC;IAC7D,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACjF,MAAM,iBAAiB,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,6BAA6B,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IACnF,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,GAAG,QAAQ,CAAC,CAAC;IACvD,MAAM,gBAAgB,GAAG,KAAK,CAAC,YAAY,GAAG,SAAS,GAAG,KAAK,CAAC,sBAAsB,CAAC;IACvF,MAAM,YAAY,GAAG,iBAAiB,GAAG,gBAAgB,IAAI,CAAC,GAAG,SAAS,CAAC;IAC3E,IAAI,CAAC,CAAC,iBAAiB,EAAE,MAAM,EAAE,gBAAgB,EAAE,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC3G,MAAM,IAAI,2BAA2B,CAAC,qEAAqE,CAAC,CAAC;IAC/G,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACzD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YACnE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;YACtD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC;YACjE,MAAM,IAAI,2BAA2B,CAAC,4DAA4D,CAAC,CAAC;QACtG,CAAC;QACD,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,gBAAgB,CAAC;QACtE,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,gBAAgB,CAAC;QACtE,gFAAgF;QAChF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC;YAC3E,MAAM,IAAI,2BAA2B,CAAC,2DAA2D,CAAC,CAAC;QACrG,CAAC;QACD,MAAM,SAAS,GAAG,aAAa,CAAC,QAAQ,CAAC,kBAAkB,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAC/E,OAAO;YACL,qBAAqB,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;YACzF,uBAAuB,EAAE,SAAS;YAClC,mCAAmC,EAAE,SAAS,GAAG,YAAY;SAC9D,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,OAAO,mBAAmB,CAAC;QACzB,UAAU,EAAE,QAAQ,CAAC,UAAU;QAC/B,0BAA0B,EAAE,KAAK,CAAC,0BAA0B,IAAI,CAAC;QACjE,sBAAsB,EAAE,KAAK,CAAC,sBAAsB;QACpD,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,iBAAiB;QACjB,mBAAmB,EAAE,MAAM;QAC3B,kBAAkB,EAAE,mBAAmB;QACvC,SAAS,EAAE,iBAAiB;QAC5B,mBAAmB,EAAE,yCAAyC;QAC9D,iBAAiB,EAAE,KAAK;QACxB,OAAO;KACR,EAAE,8CAA8C,EAAE,OAAO,EAAE;QAC1D,+IAA+I;QAC/I,yGAAyG;QACzG,qHAAqH;QACrH,kIAAkI;QAClI,0KAA0K;QAC1K,+JAA+J;QAC/J,uIAAuI;KACxI,EAAE,EAAE,KAAK,EAAE,CAAC,6IAA6I,CAAC,EAAE,CAAC,CAAC;AACjK,CAAC"}
|
|
1
|
+
{"version":3,"file":"polygon-diffraction.js","sourceRoot":"","sources":["../../src/optics/polygon-diffraction.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Diffraction PSF (point-spread function) of a polygon-shaped aperture.\n *\n * The main model gives the continuous, single-wavelength Fraunhofer (far-field) PSF density of an\n * ideal regular polygon with straight edges. The pupil is uniformly lit, has zero phase and sits on\n * the optical axis.\n * - The physical area is explicit. f/N may supply the diameter of a circle with the same area, but\n * only when the caller declares the nominal-area convention.\n * - Nothing else is assumed: no phase aberration, clipping, field dependence, curved blades, defocus\n * or multi-wavelength behaviour.\n *\n * Density = A |F/A|² / (lambda * propagationDistance)². The density integrates to 1 over the\n * infinite image plane (Parseval). It is NOT normalized over the supplied list of points. Code that\n * sums these samples must keep density × area and report truncation and convergence.\n * @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { approximationResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport { InvalidScientificInputError, requirePositiveFinite } from \"../core/validation.js\";\nimport { calculateIdealApertureGeometry, type CalculateIdealApertureInput } from \"./aperture.js\";\nimport type { SpectralWavelengthBasis } from \"../core/spectral.js\";\nimport { requireInputKeys } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\n\n/** On-axis, in-focus scalar diffraction of one ideal regular polygon pupil. */\nexport interface CalculateIdealPolygonDiffractionInput extends CalculateIdealApertureInput {\n /** Diameter of a circle with the SAME AREA as the physical polygon opening. */\n equivalentAreaPupilDiameterMm: number;\n /** Paraxial propagation distance from pupil to image. Never inferred from focus. */\n pupilToImageDistanceMm: number;\n /** Wavelength in the declared propagation medium. No air/vacuum conversion is applied. */\n wavelengthNm: number;\n wavelengthBasis: Exclude<SpectralWavelengthBasis, \"unspecified\">;\n /** Displacements from the on-axis PSF center, +X right / +Y up; at most 4096. */\n imagePointsMicrometers: readonly { x: number; y: number }[];\n}\n\n/** Samples of a continuous unit-energy PSF. This is not a normalized finite convolution kernel. */\nexport interface IdealPolygonDiffraction {\n bladeCount: number;\n firstBladeEdgeAngleDegrees: number;\n pupilToImageDistanceMm: number;\n wavelengthNm: number;\n wavelengthBasis: Exclude<SpectralWavelengthBasis, \"unspecified\">;\n pupilAreaSquareMm: number;\n pupilCircumradiusMm: number;\n pupilNormalization: \"equal-area-circle\";\n fieldAxes: \"+X right, +Y up\";\n energyNormalization: \"unit-integral-over-infinite-image-plane\";\n throughputApplied: false;\n samples: readonly {\n imagePointMicrometers: { x: number; y: number };\n /** |F/A|². Equal to 1 at the origin. Not an energy or probability weight. */\n peakNormalizedIntensity: number;\n /** Density integrating to unity over the full image plane, in 1/µm². */\n intensityDensityPerSquareMicrometer: number;\n }[];\n}\n\n/** sin(x)/x - 1, evaluated without cancellation near zero. */\nfunction sincMinusOne(x: number): number {\n if (Math.abs(x) < 0.01) {\n const x2 = x * x;\n return x2 * (-1 / 6 + x2 * (1 / 120 - x2 / 5040));\n }\n return Math.sin(x) / x - 1;\n}\n\n/**\n * Fourier transform of the polygon, written as an integral around its edges\n * using the divergence theorem (independently derived). Coordinates use a\n * circumradius of 1, so pupil size cannot affect numerical conditioning.\n * Subtracting the zero-frequency edge term (which sums to zero around the\n * closed polygon) avoids cancellation at and near the origin.\n */\nfunction peakIntensity(\n vertices: readonly { x: number; y: number }[],\n area: number,\n qx: number,\n qy: number\n): number {\n const q = Math.hypot(qx, qy);\n if (q === 0) return 1;\n const ux = qx / q;\n const uy = qy / q;\n let real = 0;\n let imaginary = 0;\n for (let index = 0; index < vertices.length; index += 1) {\n const a = vertices[index]!;\n const b = vertices[(index + 1) % vertices.length]!;\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const midpointPhase = qx * (a.x + b.x) / 2 + qy * (a.y + b.y) / 2;\n const edgePhase = (qx * dx + qy * dy) / 2;\n const sm1 = sincMinusOne(edgePhase);\n const sinc = 1 + sm1;\n const coefficient = (ux * dy - uy * dx) / area;\n // i times the edge integral: real = -Im(edge), imaginary = Re(edge).\n real += coefficient * sinc * (Math.sin(midpointPhase) / q);\n imaginary += coefficient * (sm1 - sinc * 2 * Math.sin(midpointPhase / 2) ** 2) / q;\n }\n return real * real + imaginary * imaginary;\n}\n\n/**\n * Calculates the continuous, single-wavelength Fraunhofer (far-field) PSF\n * density of an ideal regular polygon with straight edges. The pupil is\n * uniformly lit, has zero phase and sits on the optical axis.\n *\n * The physical area is explicit. f/N may supply the equal-area diameter only\n * when the caller declares the nominal-area convention. Nothing else is\n * assumed: no phase aberration, clipping, field dependence, curved blades,\n * defocus or multi-wavelength behaviour.\n *\n * Density = A |F/A|² / (lambda * propagationDistance)². It integrates to 1\n * over the infinite plane (Parseval), NOT over the supplied points. Code that\n * sums the samples must keep density × area and report truncation and\n * convergence.\n */\nexport function calculateIdealPolygonDiffractionPsf(\n input: CalculateIdealPolygonDiffractionInput\n): CalculationResult<IdealPolygonDiffraction> {\n // Reject unmodeled effects rather than silently accepting and ignoring them.\n const allowed = new Set([\n \"bladeCount\", \"firstBladeEdgeAngleDegrees\", \"equivalentAreaPupilDiameterMm\",\n \"pupilToImageDistanceMm\", \"wavelengthNm\", \"wavelengthBasis\", \"imagePointsMicrometers\"\n ]);\n if (typeof input !== \"object\" || input === null || Array.isArray(input) ||\n Object.keys(input).some((key) => !allowed.has(key))) {\n throw new InvalidConfigurationError(\"Polygon diffraction input contains unsupported fields or is not an object.\");\n }\n requirePositiveFinite(\"equivalentAreaPupilDiameterMm\", input.equivalentAreaPupilDiameterMm);\n requirePositiveFinite(\"pupilToImageDistanceMm\", input.pupilToImageDistanceMm);\n requirePositiveFinite(\"wavelengthNm\", input.wavelengthNm);\n if (input.wavelengthBasis !== \"air\" && input.wavelengthBasis !== \"vacuum\") {\n throw new InvalidConfigurationError(\"wavelengthBasis must be air or vacuum.\");\n }\n if (input.firstBladeEdgeAngleDegrees !== undefined && !Number.isFinite(input.firstBladeEdgeAngleDegrees)) {\n throw new InvalidScientificInputError(\"firstBladeEdgeAngleDegrees must be finite when supplied.\");\n }\n if (!Array.isArray(input.imagePointsMicrometers) ||\n input.imagePointsMicrometers.length === 0 || input.imagePointsMicrometers.length > 4096) {\n throw new InvalidScientificInputError(\"imagePointsMicrometers must contain 1 through 4096 points.\");\n }\n for (let index = 0; index < input.imagePointsMicrometers.length; index += 1) {\n if (!Object.hasOwn(input.imagePointsMicrometers, index)) {\n throw new InvalidScientificInputError(\"imagePointsMicrometers must not contain sparse entries.\");\n }\n }\n const geometry = calculateIdealApertureGeometry({ bladeCount: input.bladeCount, ...(input.firstBladeEdgeAngleDegrees === undefined ? {} : { firstBladeEdgeAngleDegrees: input.firstBladeEdgeAngleDegrees }) }).value;\n const unitArea = input.bladeCount * Math.sin(2 * Math.PI / input.bladeCount) / 2;\n const pupilAreaSquareMm = Math.PI * (input.equivalentAreaPupilDiameterMm / 2) ** 2;\n const radius = Math.sqrt(pupilAreaSquareMm / unitArea);\n const propagationScale = input.wavelengthNm / 1_000_000 * input.pupilToImageDistanceMm;\n const densityScale = pupilAreaSquareMm / propagationScale ** 2 / 1_000_000;\n if (![pupilAreaSquareMm, radius, propagationScale, densityScale].every((x) => Number.isFinite(x) && x > 0)) {\n throw new InvalidScientificInputError(\"Derived polygon diffraction scales must remain finite and positive.\");\n }\n const samples = input.imagePointsMicrometers.map((point) => {\n if (typeof point !== \"object\" || point === null || Array.isArray(point) ||\n !Number.isFinite(point.x) || !Number.isFinite(point.y) ||\n Object.keys(point).some((key) => key !== \"x\" && key !== \"y\")) {\n throw new InvalidScientificInputError(\"Each image point must contain finite x/y coordinates only.\");\n }\n const qx = 2 * Math.PI * (point.x / 1000) * radius / propagationScale;\n const qy = 2 * Math.PI * (point.y / 1000) * radius / propagationScale;\n // A numerical envelope, not a real-lens calibration or physical accuracy bound.\n if (!Number.isFinite(Math.hypot(qx, qy)) || Math.hypot(qx, qy) > 1_000_000) {\n throw new InvalidScientificInputError(\"Dimensionless pupil phase radius must not exceed 1000000.\");\n }\n const intensity = peakIntensity(geometry.normalizedVertices, unitArea, qx, qy);\n return {\n imagePointMicrometers: { x: point.x === 0 ? 0 : point.x, y: point.y === 0 ? 0 : point.y },\n peakNormalizedIntensity: intensity,\n intensityDensityPerSquareMicrometer: intensity * densityScale\n };\n });\n return approximationResult({\n bladeCount: geometry.bladeCount,\n firstBladeEdgeAngleDegrees: input.firstBladeEdgeAngleDegrees ?? 0,\n pupilToImageDistanceMm: input.pupilToImageDistanceMm,\n wavelengthNm: input.wavelengthNm,\n wavelengthBasis: input.wavelengthBasis,\n pupilAreaSquareMm,\n pupilCircumradiusMm: radius,\n pupilNormalization: \"equal-area-circle\",\n fieldAxes: \"+X right, +Y up\",\n energyNormalization: \"unit-integral-over-infinite-image-plane\",\n throughputApplied: false,\n samples\n }, \"ideal-regular-polygon-fraunhofer-diffraction\", \"1.0.0\", [\n \"Uniform unit pupil amplitude, zero phase, ideal regular straight-edged polygon; on-axis in-focus scalar paraxial Fraunhofer propagation only.\",\n \"Wavelength is supplied in its declared propagation medium; no wavelength-basis conversion is performed.\",\n \"Equal-area diameter fixes physical pupil area, not circumradius or inradius; no optical throughput loss is applied.\",\n \"Continuous PSF density has unit integral over the infinite image plane. Point samples are not a finite energy-normalized kernel.\",\n \"The analytical polygon boundary integral has no FFT/pupil-grid aliasing; downstream image-plane sampling and finite-support truncation still require convergence checks.\",\n \"No real-lens calibration, aberration, defocus, mechanical clipping, curved blades, field dependence, polarization, sensor response or stray light is modeled.\",\n \"Circular Airy remains a separate named diagnostic; do not stack this diffraction PSF over an already diffracted complex-pupil result.\"\n ], { notes: [\"No quantified physical-model uncertainty is asserted. Numerical tolerances in tests are validation evidence, not real-lens accuracy bounds.\"] });\n}\n\n/** On-axis scalar Fraunhofer diffraction of one arbitrary simple polygon pupil. */\nexport interface CalculatePolygonPupilFraunhoferPsfInput {\n /**\n * Simple (non-self-intersecting) pupil polygon in pupil-plane millimetres, +X right / +Y up,\n * with 3 to 4096 vertices. For example, the cat's-eye pupil from calculateMechanicalVignetting().\n */\n pupilVerticesMm: readonly { x: number; y: number }[];\n /** Paraxial propagation distance from pupil to image. Never inferred from focus. */\n pupilToImageDistanceMm: number;\n /** Wavelength in the declared propagation medium. No air/vacuum conversion is applied. */\n wavelengthNm: number;\n wavelengthBasis: Exclude<SpectralWavelengthBasis, \"unspecified\">;\n /** Displacements from the PSF centre (the geometric image point), +X right / +Y up; at most 4096. */\n imagePointsMicrometers: readonly { x: number; y: number }[];\n}\n\nexport interface PolygonPupilFraunhoferPsf {\n pupilAreaSquareMm: number;\n pupilToImageDistanceMm: number;\n wavelengthNm: number;\n wavelengthBasis: Exclude<SpectralWavelengthBasis, \"unspecified\">;\n fieldAxes: \"+X right, +Y up\";\n energyNormalization: \"unit-integral-over-infinite-image-plane\";\n throughputApplied: false;\n samples: readonly {\n imagePointMicrometers: { x: number; y: number };\n /** |F/A|²; unity at the origin. */\n peakNormalizedIntensity: number;\n /** Density integrating to unity over the full image plane, in 1/µm². */\n intensityDensityPerSquareMicrometer: number;\n }[];\n}\n\nfunction requirePlanarPoint(value: unknown, path: string): { x: number; y: number } {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new InvalidScientificInputError(`${path} must contain finite x/y coordinates only.`);\n }\n const record = value as Record<string, unknown>;\n if (\n Object.keys(record).some((key) => key !== \"x\" && key !== \"y\") ||\n typeof record.x !== \"number\" || typeof record.y !== \"number\" ||\n !Number.isFinite(record.x) || !Number.isFinite(record.y)\n ) {\n throw new InvalidScientificInputError(`${path} must contain finite x/y coordinates only.`);\n }\n return { x: record.x, y: record.y };\n}\n\n/**\n * Continuous, single-wavelength Fraunhofer PSF density for any simple polygon pupil that is uniformly\n * lit and has zero phase (for example a cat's-eye pupil from mechanical vignetting).\n *\n * It uses the same analytic edge integral as the regular-polygon model, so there is no aliasing from\n * a pupil grid. Moving the pupil off the axis only adds a linear phase; the intensity does not\n * change. Density = A |F/A|² / (lambda z)², and it integrates to 1 over the infinite plane.\n */\nexport function calculatePolygonPupilFraunhoferPsf(\n input: CalculatePolygonPupilFraunhoferPsfInput\n): CalculationResult<PolygonPupilFraunhoferPsf> {\n requireInputKeys(input, \"calculatePolygonPupilFraunhoferPsf\", [\"pupilVerticesMm\", \"pupilToImageDistanceMm\", \"wavelengthNm\", \"wavelengthBasis\", \"imagePointsMicrometers\"]);\n requirePositiveFinite(\"pupilToImageDistanceMm\", input.pupilToImageDistanceMm);\n requirePositiveFinite(\"wavelengthNm\", input.wavelengthNm);\n if (input.wavelengthBasis !== \"air\" && input.wavelengthBasis !== \"vacuum\") {\n throw new InvalidConfigurationError(\"wavelengthBasis must be air or vacuum.\");\n }\n if (!Array.isArray(input.pupilVerticesMm) || input.pupilVerticesMm.length < 3 ||\n input.pupilVerticesMm.length > 4096) {\n throw new InvalidScientificInputError(\"pupilVerticesMm must contain 3 through 4096 vertices.\");\n }\n if (!Array.isArray(input.imagePointsMicrometers) ||\n input.imagePointsMicrometers.length === 0 || input.imagePointsMicrometers.length > 4096) {\n throw new InvalidScientificInputError(\"imagePointsMicrometers must contain 1 through 4096 points.\");\n }\n const vertices = input.pupilVerticesMm.map((vertex, index) =>\n requirePlanarPoint(vertex, `pupilVerticesMm[${index}]`));\n // Centre and scale the polygon for conditioning; translation changes only the phase of F.\n const cx = vertices.reduce((sum, v) => sum + v.x, 0) / vertices.length;\n const cy = vertices.reduce((sum, v) => sum + v.y, 0) / vertices.length;\n const scale = Math.max(...vertices.map((v) => Math.hypot(v.x - cx, v.y - cy)));\n if (!(scale > 0) || !Number.isFinite(scale)) {\n throw new InvalidScientificInputError(\"pupilVerticesMm must span a finite non-zero region.\");\n }\n let normalized = vertices.map((v) => ({ x: (v.x - cx) / scale, y: (v.y - cy) / scale }));\n let twiceArea = 0;\n for (let index = 0; index < normalized.length; index += 1) {\n const a = normalized[index]!;\n const b = normalized[(index + 1) % normalized.length]!;\n twiceArea += a.x * b.y - b.x * a.y;\n }\n if (twiceArea < 0) {\n normalized = [...normalized].reverse();\n twiceArea = -twiceArea;\n }\n const unitArea = twiceArea / 2;\n const pupilAreaSquareMm = unitArea * scale * scale;\n const propagationScale = input.wavelengthNm / 1_000_000 * input.pupilToImageDistanceMm;\n const densityScale = pupilAreaSquareMm / propagationScale ** 2 / 1_000_000;\n if (!(unitArea > 1e-12) ||\n ![pupilAreaSquareMm, propagationScale, densityScale].every((x) => Number.isFinite(x) && x > 0)) {\n throw new InvalidScientificInputError(\"Polygon pupil area and derived scales must remain finite and positive.\");\n }\n const samples = input.imagePointsMicrometers.map((value, index) => {\n const point = requirePlanarPoint(value, `imagePointsMicrometers[${index}]`);\n const qx = 2 * Math.PI * (point.x / 1000) * scale / propagationScale;\n const qy = 2 * Math.PI * (point.y / 1000) * scale / propagationScale;\n if (!Number.isFinite(Math.hypot(qx, qy)) || Math.hypot(qx, qy) > 1_000_000) {\n throw new InvalidScientificInputError(\"Dimensionless pupil phase radius must not exceed 1000000.\");\n }\n const intensity = peakIntensity(normalized, unitArea, qx, qy);\n return {\n imagePointMicrometers: { x: point.x === 0 ? 0 : point.x, y: point.y === 0 ? 0 : point.y },\n peakNormalizedIntensity: intensity,\n intensityDensityPerSquareMicrometer: intensity * densityScale\n };\n });\n return approximationResult({\n pupilAreaSquareMm,\n pupilToImageDistanceMm: input.pupilToImageDistanceMm,\n wavelengthNm: input.wavelengthNm,\n wavelengthBasis: input.wavelengthBasis,\n fieldAxes: \"+X right, +Y up\",\n energyNormalization: \"unit-integral-over-infinite-image-plane\",\n throughputApplied: false,\n samples\n }, \"polygon-pupil-fraunhofer-diffraction\", \"1.0.0\", [\n \"Uniform unit pupil amplitude and zero phase over a caller-declared simple polygon; scalar paraxial Fraunhofer propagation.\",\n \"The PSF is centred on the geometric image point; a pupil offset from the optical axis adds only a linear phase.\",\n \"Continuous PSF density has unit integral over the infinite image plane. Point samples are not a finite energy-normalized kernel.\",\n \"Pupil-area throughput (for example mechanical vignetting) is reported separately and not applied to the density.\",\n \"No aberration, defocus, polarization, sensor response or stray light is modeled.\"\n ], { notes: [\"No quantified physical-model uncertainty is asserted. Numerical tolerances in tests are validation evidence, not real-lens accuracy bounds.\"] });\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type EvidenceProvenance } from "../core/evidence-provenance.js";
|
|
2
|
-
/** Exact, generic camera
|
|
2
|
+
/** Exact, generic camera, lens and acquisition state. Nothing is interpolated implicitly. */
|
|
3
3
|
export interface OpticalProfileState {
|
|
4
4
|
bodyId: string;
|
|
5
5
|
bodyVersion: string;
|
|
@@ -14,7 +14,7 @@ export interface OpticalProfileState {
|
|
|
14
14
|
frameRateHz: number;
|
|
15
15
|
stabilizationMode: string;
|
|
16
16
|
}
|
|
17
|
-
/**
|
|
17
|
+
/** Evidence for a generic approximation. It never implies a measured calibration. */
|
|
18
18
|
export interface GenericOpticalEvidence {
|
|
19
19
|
kind: "generic-parametric";
|
|
20
20
|
basis: string;
|
|
@@ -31,12 +31,11 @@ export declare function positive(value: unknown, name: string): number;
|
|
|
31
31
|
export declare function textValue(value: unknown): string;
|
|
32
32
|
/** @internal */
|
|
33
33
|
export declare function choice<T extends string>(value: unknown, choices: readonly T[]): T;
|
|
34
|
-
/** @internal
|
|
34
|
+
/** @internal Rejects gaps and unbounded work. Consumers reject duplicates. */
|
|
35
35
|
export declare function list(value: unknown, maximum?: number): unknown[];
|
|
36
|
-
/** Parses a complete exact-state binding, including still
|
|
36
|
+
/** Parses a complete exact-state binding, including still, video and output settings. */
|
|
37
37
|
export declare function parseOpticalProfileState(value: unknown): OpticalProfileState;
|
|
38
|
-
/** @internal Exact binding;
|
|
38
|
+
/** @internal Exact binding. A mismatch fails; it is never extrapolated. */
|
|
39
39
|
export declare function requireSameState(expected: OpticalProfileState, actual: OpticalProfileState): void;
|
|
40
40
|
/** @internal */
|
|
41
41
|
export declare function parseEvidence(value: unknown): GenericOpticalEvidence;
|
|
42
|
-
//# sourceMappingURL=profile-contract.d.ts.map
|
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
/**
|
|
3
|
-
* Generic optical state
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* Generic optical state. It ties one camera body, lens, version, acquisition setting and output
|
|
4
|
+
* configuration to explicit evidence for the approximation used.
|
|
5
|
+
*
|
|
6
|
+
* These identities do not certify manufacturer calibration. Correction and stray-light code checks
|
|
7
|
+
* that the state matches exactly before it applies any declared coefficients.
|
|
7
8
|
* @see docs/RELEASE_1_0.md and the corresponding domain guide.
|
|
8
9
|
*/
|
|
9
10
|
import { InvalidScientificInputError } from "../core/validation.js";
|
|
10
11
|
import { parseEvidenceList } from "../core/evidence-provenance.js";
|
|
12
|
+
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
11
13
|
/** @internal Strict shared profile parser helpers. */
|
|
12
14
|
export function record(value, keys) {
|
|
13
15
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
14
|
-
throw new
|
|
16
|
+
throw new InvalidConfigurationError("Expected a profile object.");
|
|
15
17
|
}
|
|
16
18
|
const result = value;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
const unknown = Object.keys(result).find((key) => !keys.includes(key));
|
|
20
|
+
if (unknown !== undefined) {
|
|
21
|
+
throw new InvalidConfigurationError(`Unknown profile field. Unknown field ${JSON.stringify(unknown)}.`);
|
|
19
22
|
}
|
|
20
23
|
return result;
|
|
21
24
|
}
|
|
@@ -43,10 +46,10 @@ export function textValue(value) {
|
|
|
43
46
|
/** @internal */
|
|
44
47
|
export function choice(value, choices) {
|
|
45
48
|
if (!choices.includes(value))
|
|
46
|
-
throw new
|
|
49
|
+
throw new InvalidConfigurationError("Unknown profile enum.");
|
|
47
50
|
return value;
|
|
48
51
|
}
|
|
49
|
-
/** @internal
|
|
52
|
+
/** @internal Rejects gaps and unbounded work. Consumers reject duplicates. */
|
|
50
53
|
export function list(value, maximum = 4096) {
|
|
51
54
|
if (!Array.isArray(value) || value.length > maximum ||
|
|
52
55
|
Array.from({ length: value.length }, (_, index) => index in value).includes(false)) {
|
|
@@ -54,7 +57,7 @@ export function list(value, maximum = 4096) {
|
|
|
54
57
|
}
|
|
55
58
|
return value;
|
|
56
59
|
}
|
|
57
|
-
/** Parses a complete exact-state binding, including still
|
|
60
|
+
/** Parses a complete exact-state binding, including still, video and output settings. */
|
|
58
61
|
export function parseOpticalProfileState(value) {
|
|
59
62
|
const r = record(value, ["bodyId", "bodyVersion", "lensId", "lensVersion", "focalLengthMm",
|
|
60
63
|
"aperture", "focusDistanceM", "captureMode", "outputWidth", "outputHeight", "frameRateHz", "stabilizationMode"]);
|
|
@@ -77,7 +80,7 @@ export function parseOpticalProfileState(value) {
|
|
|
77
80
|
stabilizationMode: textValue(r.stabilizationMode)
|
|
78
81
|
};
|
|
79
82
|
}
|
|
80
|
-
/** @internal Exact binding;
|
|
83
|
+
/** @internal Exact binding. A mismatch fails; it is never extrapolated. */
|
|
81
84
|
export function requireSameState(expected, actual) {
|
|
82
85
|
if (JSON.stringify(parseOpticalProfileState(expected)) !== JSON.stringify(parseOpticalProfileState(actual))) {
|
|
83
86
|
throw new InvalidScientificInputError("Profile is not applicable to this exact camera/lens state.");
|