@photivra/engine 1.5.0 → 2.1.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 +414 -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 +116 -9
- package/dist/capture/native-raw-development.js +221 -62
- 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 +65 -12
- package/dist/capture/native-raw.js +81 -19
- 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/diffraction-provider.d.ts +30 -0
- package/dist/facade/diffraction-provider.js +127 -0
- package/dist/facade/diffraction-provider.js.map +1 -0
- package/dist/facade/host-yield.d.ts +7 -0
- package/dist/facade/host-yield.js +19 -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 +363 -0
- package/dist/facade/simulate-capture.js +1281 -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 +91 -25
- package/dist/index.js +60 -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-psf-profile.d.ts +118 -0
- package/dist/optics/diffraction-psf-profile.js +252 -0
- package/dist/optics/diffraction-psf-profile.js.map +1 -0
- 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 +777 -2
- package/docs/QUICK_START.md +663 -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 -8
- package/docs/api/capture-native-raw-dng.md +84 -0
- package/docs/api/capture-native-raw.md +21 -10
- 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 +2253 -3
- 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 +397 -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-psf-profile.md +96 -0
- 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 -11
- 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/DENSE_PUPIL_QUALIFICATION.md +0 -121
- 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 -54
- 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_1_5_0.md +0 -105
- 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/SEPARABLE_EMISSION_DRAFT.md +0 -103
- 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/dense-pupil-2026-10-06/pilot.jsonl +0 -6
- 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
|
@@ -1,28 +1,40 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
3
|
+
* Thin-lens depth of field (DoF) and defocus blur.
|
|
4
|
+
*
|
|
5
|
+
* Depth-of-field limits are exact for a thin lens. They use the hyperfocal distance
|
|
6
|
+
* H = f^2/(Nc) + f:
|
|
7
|
+
* near = s(H - f)/(H + s - 2f)
|
|
8
|
+
* far = s(H - f)/(H - s), infinite (null) when s >= H
|
|
9
|
+
* The model is geometric. It does not include diffraction, aberrations, focus breathing, pupil
|
|
10
|
+
* magnification or macro (high-magnification) effects.
|
|
11
|
+
*
|
|
12
|
+
* The defocus circle is the geometric blur-circle diameter at the sensor for a subject plane that is
|
|
13
|
+
* not at the focus distance.
|
|
14
|
+
* @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers
|
|
15
|
+
* and support limits.
|
|
11
16
|
*/
|
|
12
17
|
import { calculatedResult } from "../core/calculation-result.js";
|
|
13
18
|
import { InvalidScientificInputError, requirePositiveFinite } from "../core/validation.js";
|
|
14
19
|
import { calculateThinLensImageDistance } from "./thin-lens.js";
|
|
20
|
+
import { requireInputKeys } from "../core/record-validation.js";
|
|
15
21
|
/**
|
|
16
|
-
* Calculates thin-lens depth-of-field limits
|
|
17
|
-
*
|
|
22
|
+
* Calculates exact thin-lens depth-of-field limits. With hyperfocal
|
|
23
|
+
* distance H = f^2/(Nc) + f and focus distance s, the near limit is
|
|
24
|
+
* s(H - f)/(H + s - 2f) and the far limit is s(H - f)/(H - s), which is
|
|
25
|
+
* infinite (`null`) when s >= H. At both limits the geometric defocus circle
|
|
26
|
+
* from {@link calculateDefocusCircle} equals the supplied circle of confusion.
|
|
27
|
+
* The circle of confusion must be smaller than the aperture diameter f/N;
|
|
28
|
+
* otherwise the near limit would fall inside the focal length.
|
|
18
29
|
*
|
|
19
|
-
* The model is geometric
|
|
20
|
-
* focus breathing, pupil magnification
|
|
30
|
+
* The model is geometric. It does not include diffraction, aberrations,
|
|
31
|
+
* focus breathing, pupil magnification or macro (high-magnification) effects.
|
|
21
32
|
*
|
|
22
33
|
* @param input Lens, focus, aperture, and acceptable blur-circle inputs.
|
|
23
34
|
* @returns Hyperfocal, near, and far depth-of-field distances.
|
|
24
35
|
*/
|
|
25
36
|
export function calculateDepthOfField(input) {
|
|
37
|
+
requireInputKeys(input, "calculateDepthOfField", ["focalLengthMm", "aperture", "focusDistanceM", "circleOfConfusionMm"]);
|
|
26
38
|
requirePositiveFinite("focalLengthMm", input.focalLengthMm);
|
|
27
39
|
requirePositiveFinite("aperture", input.aperture);
|
|
28
40
|
requirePositiveFinite("focusDistanceM", input.focusDistanceM);
|
|
@@ -31,22 +43,37 @@ export function calculateDepthOfField(input) {
|
|
|
31
43
|
if (focusDistanceMm <= input.focalLengthMm) {
|
|
32
44
|
throw new InvalidScientificInputError("focusDistanceM must place the focus plane beyond the focal length.");
|
|
33
45
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
46
|
+
// The near limit lies beyond the focal length only when H - f = f^2/(Nc) > f,
|
|
47
|
+
// i.e. c < f/N (the entrance-pupil diameter). A blur circle at least as large
|
|
48
|
+
// as the pupil itself has no real-image depth-of-field solution.
|
|
49
|
+
if (input.circleOfConfusionMm >= input.focalLengthMm / input.aperture) {
|
|
50
|
+
throw new InvalidScientificInputError("circleOfConfusionMm must be smaller than the aperture diameter focalLengthMm / aperture.");
|
|
51
|
+
}
|
|
52
|
+
// H - f = f^2 / (N c), kept separately to avoid cancellation.
|
|
53
|
+
const hyperfocalOffsetMm = (input.focalLengthMm * input.focalLengthMm) /
|
|
54
|
+
(input.aperture * input.circleOfConfusionMm);
|
|
55
|
+
const hyperfocalDistanceMm = hyperfocalOffsetMm + input.focalLengthMm;
|
|
56
|
+
// Exact thin-lens limits. The defocus-circle diameter for a subject at d
|
|
57
|
+
// while focused at s is c(d) = f^2 |s - d| / (N d (s - f)). Solving
|
|
58
|
+
// c(d) = c with H = f^2 / (N c) + f gives
|
|
59
|
+
// near = s (H - f) / (H + s - 2f) = s (H - f) / ((H - f) + (s - f))
|
|
60
|
+
// far = s (H - f) / (H - s), infinite when s >= H.
|
|
61
|
+
const nearLimitMm = (focusDistanceMm * hyperfocalOffsetMm) /
|
|
62
|
+
(hyperfocalOffsetMm + (focusDistanceMm - input.focalLengthMm));
|
|
63
|
+
// Compare against the reported hyperfocal distance in metres as well, so a
|
|
64
|
+
// caller focusing at exactly the returned hyperfocalDistanceM always gets an
|
|
65
|
+
// infinite far limit despite millimetre/metre rounding.
|
|
66
|
+
const hyperfocalDistanceM = hyperfocalDistanceMm / 1000;
|
|
67
|
+
const farDenominator = hyperfocalDistanceMm - focusDistanceMm;
|
|
68
|
+
const farLimitMm = farDenominator <= 0 || input.focusDistanceM >= hyperfocalDistanceM
|
|
42
69
|
? null
|
|
43
|
-
: (
|
|
70
|
+
: (focusDistanceMm * hyperfocalOffsetMm) / farDenominator;
|
|
44
71
|
return calculatedResult({
|
|
45
|
-
hyperfocalDistanceM
|
|
72
|
+
hyperfocalDistanceM,
|
|
46
73
|
nearLimitM: nearLimitMm / 1000,
|
|
47
74
|
farLimitM: farLimitMm === null ? null : farLimitMm / 1000,
|
|
48
75
|
totalDepthOfFieldM: farLimitMm === null ? null : (farLimitMm - nearLimitMm) / 1000
|
|
49
|
-
}, "thin-lens-depth-of-field", "1.
|
|
76
|
+
}, "thin-lens-depth-of-field", "1.1.0", [
|
|
50
77
|
"Geometric thin-lens model",
|
|
51
78
|
"Circle of confusion is supplied by the caller",
|
|
52
79
|
"Macro/high-magnification effects are not modeled"
|
|
@@ -54,12 +81,14 @@ export function calculateDepthOfField(input) {
|
|
|
54
81
|
}
|
|
55
82
|
/**
|
|
56
83
|
* Calculates the geometric defocus-circle diameter at the sensor plane for a
|
|
57
|
-
* subject plane away from the selected focus plane
|
|
84
|
+
* subject plane away from the selected focus plane, using the stable closed
|
|
85
|
+
* form c = f^2 |s - d| / (N d (s - f)) (model 1.1.0).
|
|
58
86
|
*
|
|
59
87
|
* @param input Lens, aperture, focus-plane, and subject-plane distances.
|
|
60
88
|
* @returns Geometric blur-circle diameter.
|
|
61
89
|
*/
|
|
62
90
|
export function calculateDefocusCircle(input) {
|
|
91
|
+
requireInputKeys(input, "calculateDefocusCircle", ["focalLengthMm", "aperture", "focusDistanceM", "subjectDistanceM"]);
|
|
63
92
|
return calculateDefocusCircleUsingFocusProjection(input);
|
|
64
93
|
}
|
|
65
94
|
/** @internal Reuses a projection already calculated for this exact POC request. */
|
|
@@ -97,10 +126,21 @@ export function calculateDefocusCircleUsingFocusProjection(input, projection) {
|
|
|
97
126
|
}
|
|
98
127
|
throw error;
|
|
99
128
|
}
|
|
129
|
+
// Both image distances are still resolved above, so the thin-lens domain checks
|
|
130
|
+
// and the reused-projection identity check still run.
|
|
131
|
+
void focusImageDistanceMm;
|
|
132
|
+
void subjectImageDistanceMm;
|
|
100
133
|
const apertureDiameterMm = input.focalLengthMm / input.aperture;
|
|
134
|
+
const focusDistanceMm = input.focusDistanceM * 1000;
|
|
135
|
+
const subjectDistanceMm = input.subjectDistanceM * 1000;
|
|
136
|
+
// Closed form of D |v_d - v_s| / v_d with v = f x / (x - f) (Gaussian thin lens):
|
|
137
|
+
// c = f^2 |s - d| / (N d (s - f)).
|
|
138
|
+
// It avoids subtracting two nearly equal image distances (catastrophic
|
|
139
|
+
// cancellation for distant subjects) and is grouped as bounded ratios so the
|
|
140
|
+
// intermediate products cannot overflow for finite in-domain inputs.
|
|
101
141
|
const diameterMm = apertureDiameterMm *
|
|
102
|
-
(Math.abs(
|
|
103
|
-
|
|
104
|
-
return calculatedResult({ diameterMm }, "thin-lens-defocus-circle", "1.
|
|
142
|
+
(Math.abs(focusDistanceMm - subjectDistanceMm) / subjectDistanceMm) *
|
|
143
|
+
(input.focalLengthMm / (focusDistanceMm - input.focalLengthMm));
|
|
144
|
+
return calculatedResult({ diameterMm }, "thin-lens-defocus-circle", "1.1.0", ["Geometric thin-lens model", "Ideal circular entrance pupil"]);
|
|
105
145
|
}
|
|
106
146
|
//# sourceMappingURL=depth-of-field.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"depth-of-field.js","sourceRoot":"","sources":["../../src/optics/depth-of-field.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"depth-of-field.js","sourceRoot":"","sources":["../../src/optics/depth-of-field.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,gBAAgB,EAEjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,EACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAsBhE;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAiC;IAEjC,gBAAgB,CAAC,KAAK,EAAE,uBAAuB,EAAE,CAAC,eAAe,EAAE,UAAU,EAAE,gBAAgB,EAAE,qBAAqB,CAAC,CAAC,CAAC;IACzH,qBAAqB,CAAC,eAAe,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAC5D,qBAAqB,CAAC,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAClD,qBAAqB,CAAC,gBAAgB,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAC9D,qBAAqB,CAAC,qBAAqB,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAExE,MAAM,eAAe,GAAG,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC;IACpD,IAAI,eAAe,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;QAC3C,MAAM,IAAI,2BAA2B,CACnC,oEAAoE,CACrE,CAAC;IACJ,CAAC;IACD,8EAA8E;IAC9E,8EAA8E;IAC9E,iEAAiE;IACjE,IAAI,KAAK,CAAC,mBAAmB,IAAI,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QACtE,MAAM,IAAI,2BAA2B,CACnC,0FAA0F,CAC3F,CAAC;IACJ,CAAC;IAED,8DAA8D;IAC9D,MAAM,kBAAkB,GACtB,CAAC,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;QAC3C,CAAC,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAC/C,MAAM,oBAAoB,GAAG,kBAAkB,GAAG,KAAK,CAAC,aAAa,CAAC;IAEtE,yEAAyE;IACzE,oEAAoE;IACpE,0CAA0C;IAC1C,sEAAsE;IACtE,sDAAsD;IACtD,MAAM,WAAW,GACf,CAAC,eAAe,GAAG,kBAAkB,CAAC;QACtC,CAAC,kBAAkB,GAAG,CAAC,eAAe,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;IAEjE,2EAA2E;IAC3E,6EAA6E;IAC7E,wDAAwD;IACxD,MAAM,mBAAmB,GAAG,oBAAoB,GAAG,IAAI,CAAC;IACxD,MAAM,cAAc,GAAG,oBAAoB,GAAG,eAAe,CAAC;IAC9D,MAAM,UAAU,GACd,cAAc,IAAI,CAAC,IAAI,KAAK,CAAC,cAAc,IAAI,mBAAmB;QAChE,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,eAAe,GAAG,kBAAkB,CAAC,GAAG,cAAc,CAAC;IAE9D,OAAO,gBAAgB,CACrB;QACE,mBAAmB;QACnB,UAAU,EAAE,WAAW,GAAG,IAAI;QAC9B,SAAS,EAAE,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,GAAG,IAAI;QACzD,kBAAkB,EAChB,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,IAAI;KACjE,EACD,0BAA0B,EAC1B,OAAO,EACP;QACE,2BAA2B;QAC3B,+CAA+C;QAC/C,kDAAkD;KACnD,CACF,CAAC;AACJ,CAAC;AAkBD;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACpC,KAAkC;IAElC,gBAAgB,CAAC,KAAK,EAAE,wBAAwB,EAAE,CAAC,eAAe,EAAE,UAAU,EAAE,gBAAgB,EAAE,kBAAkB,CAAC,CAAC,CAAC;IACvH,OAAO,0CAA0C,CAAC,KAAK,CAAC,CAAC;AAC3D,CAAC;AASD,mFAAmF;AACnF,MAAM,UAAU,0CAA0C,CACxD,KAAkC,EAClC,UAA2C;IAE3C,qBAAqB,CAAC,eAAe,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAC5D,qBAAqB,CAAC,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAClD,qBAAqB,CAAC,gBAAgB,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAC9D,qBAAqB,CAAC,kBAAkB,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAElE,IAAI,oBAA4B,CAAC;IACjC,IAAI,sBAA8B,CAAC;IACnC,IAAI,CAAC;QACH,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,UAAU,CAAC,aAAa,KAAK,KAAK,CAAC,aAAa;gBAChD,UAAU,CAAC,cAAc,KAAK,KAAK,CAAC,cAAc;gBAClD,KAAK,CAAC,cAAc,GAAG,IAAI,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;gBACvD,MAAM,IAAI,2BAA2B,CAAC,8DAA8D,CAAC,CAAC;YACxG,CAAC;YACD,qBAAqB,CAAC,8BAA8B,EAAE,UAAU,CAAC,eAAe,CAAC,CAAC;YAClF,oBAAoB,GAAG,UAAU,CAAC,eAAe,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,oBAAoB,GAAG,8BAA8B,CAAC;gBACpD,aAAa,EAAE,KAAK,CAAC,aAAa;gBAClC,eAAe,EAAE,KAAK,CAAC,cAAc;aACtC,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC;QAC3B,CAAC;QACD,sBAAsB,GAAG,8BAA8B,CAAC;YACtD,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,eAAe,EAAE,KAAK,CAAC,gBAAgB;SACxC,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,2BAA2B,EAAE,CAAC;YACjD,MAAM,IAAI,2BAA2B,CACnC,sEAAsE,CACvE,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IACD,gFAAgF;IAChF,sDAAsD;IACtD,KAAK,oBAAoB,CAAC;IAC1B,KAAK,sBAAsB,CAAC;IAC5B,MAAM,kBAAkB,GAAG,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC;IAChE,MAAM,eAAe,GAAG,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC;IACpD,MAAM,iBAAiB,GAAG,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAExD,kFAAkF;IAClF,qCAAqC;IACrC,uEAAuE;IACvE,6EAA6E;IAC7E,qEAAqE;IACrE,MAAM,UAAU,GACd,kBAAkB;QAClB,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,iBAAiB,CAAC,GAAG,iBAAiB,CAAC;QACnE,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC,eAAe,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;IAElE,OAAO,gBAAgB,CACrB,EAAE,UAAU,EAAE,EACd,0BAA0B,EAC1B,OAAO,EACP,CAAC,2BAA2B,EAAE,+BAA+B,CAAC,CAC/D,CAAC;AACJ,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Thin-lens depth of field (DoF) and defocus blur.\n *\n * Depth-of-field limits are exact for a thin lens. They use the hyperfocal distance\n * H = f^2/(Nc) + f:\n * near = s(H - f)/(H + s - 2f)\n * far = s(H - f)/(H - s), infinite (null) when s >= H\n * The model is geometric. It does not include diffraction, aberrations, focus breathing, pupil\n * magnification or macro (high-magnification) effects.\n *\n * The defocus circle is the geometric blur-circle diameter at the sensor for a subject plane that is\n * not at the focus distance.\n * @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport {\n calculatedResult,\n type CalculationResult\n} from \"../core/calculation-result.js\";\nimport {\n InvalidScientificInputError,\n requirePositiveFinite\n} from \"../core/validation.js\";\nimport { calculateThinLensImageDistance } from \"./thin-lens.js\";\nimport { requireInputKeys } from \"../core/record-validation.js\";\n\nexport interface CalculateDepthOfFieldInput {\n /** Lens focal length in millimetres. */\n focalLengthMm: number;\n /** F-number. */\n aperture: number;\n /** Focus distance from the lens plane in metres. */\n focusDistanceM: number;\n /** Acceptable circle of confusion diameter in millimetres. */\n circleOfConfusionMm: number;\n}\n\nexport interface DepthOfField {\n hyperfocalDistanceM: number;\n nearLimitM: number;\n /** Null represents an infinite far limit. */\n farLimitM: number | null;\n /** Null represents infinite total depth of field. */\n totalDepthOfFieldM: number | null;\n}\n\n/**\n * Calculates exact thin-lens depth-of-field limits. With hyperfocal\n * distance H = f^2/(Nc) + f and focus distance s, the near limit is\n * s(H - f)/(H + s - 2f) and the far limit is s(H - f)/(H - s), which is\n * infinite (`null`) when s >= H. At both limits the geometric defocus circle\n * from {@link calculateDefocusCircle} equals the supplied circle of confusion.\n * The circle of confusion must be smaller than the aperture diameter f/N;\n * otherwise the near limit would fall inside the focal length.\n *\n * The model is geometric. It does not include diffraction, aberrations,\n * focus breathing, pupil magnification or macro (high-magnification) effects.\n *\n * @param input Lens, focus, aperture, and acceptable blur-circle inputs.\n * @returns Hyperfocal, near, and far depth-of-field distances.\n */\nexport function calculateDepthOfField(\n input: CalculateDepthOfFieldInput\n): CalculationResult<DepthOfField> {\n requireInputKeys(input, \"calculateDepthOfField\", [\"focalLengthMm\", \"aperture\", \"focusDistanceM\", \"circleOfConfusionMm\"]);\n requirePositiveFinite(\"focalLengthMm\", input.focalLengthMm);\n requirePositiveFinite(\"aperture\", input.aperture);\n requirePositiveFinite(\"focusDistanceM\", input.focusDistanceM);\n requirePositiveFinite(\"circleOfConfusionMm\", input.circleOfConfusionMm);\n\n const focusDistanceMm = input.focusDistanceM * 1000;\n if (focusDistanceMm <= input.focalLengthMm) {\n throw new InvalidScientificInputError(\n \"focusDistanceM must place the focus plane beyond the focal length.\"\n );\n }\n // The near limit lies beyond the focal length only when H - f = f^2/(Nc) > f,\n // i.e. c < f/N (the entrance-pupil diameter). A blur circle at least as large\n // as the pupil itself has no real-image depth-of-field solution.\n if (input.circleOfConfusionMm >= input.focalLengthMm / input.aperture) {\n throw new InvalidScientificInputError(\n \"circleOfConfusionMm must be smaller than the aperture diameter focalLengthMm / aperture.\"\n );\n }\n\n // H - f = f^2 / (N c), kept separately to avoid cancellation.\n const hyperfocalOffsetMm =\n (input.focalLengthMm * input.focalLengthMm) /\n (input.aperture * input.circleOfConfusionMm);\n const hyperfocalDistanceMm = hyperfocalOffsetMm + input.focalLengthMm;\n\n // Exact thin-lens limits. The defocus-circle diameter for a subject at d\n // while focused at s is c(d) = f^2 |s - d| / (N d (s - f)). Solving\n // c(d) = c with H = f^2 / (N c) + f gives\n // near = s (H - f) / (H + s - 2f) = s (H - f) / ((H - f) + (s - f))\n // far = s (H - f) / (H - s), infinite when s >= H.\n const nearLimitMm =\n (focusDistanceMm * hyperfocalOffsetMm) /\n (hyperfocalOffsetMm + (focusDistanceMm - input.focalLengthMm));\n\n // Compare against the reported hyperfocal distance in metres as well, so a\n // caller focusing at exactly the returned hyperfocalDistanceM always gets an\n // infinite far limit despite millimetre/metre rounding.\n const hyperfocalDistanceM = hyperfocalDistanceMm / 1000;\n const farDenominator = hyperfocalDistanceMm - focusDistanceMm;\n const farLimitMm =\n farDenominator <= 0 || input.focusDistanceM >= hyperfocalDistanceM\n ? null\n : (focusDistanceMm * hyperfocalOffsetMm) / farDenominator;\n\n return calculatedResult(\n {\n hyperfocalDistanceM,\n nearLimitM: nearLimitMm / 1000,\n farLimitM: farLimitMm === null ? null : farLimitMm / 1000,\n totalDepthOfFieldM:\n farLimitMm === null ? null : (farLimitMm - nearLimitMm) / 1000\n },\n \"thin-lens-depth-of-field\",\n \"1.1.0\",\n [\n \"Geometric thin-lens model\",\n \"Circle of confusion is supplied by the caller\",\n \"Macro/high-magnification effects are not modeled\"\n ]\n );\n}\n\nexport interface CalculateDefocusCircleInput {\n /** Lens focal length in millimetres. */\n focalLengthMm: number;\n /** F-number. */\n aperture: number;\n /** Focus-plane distance from the lens plane in metres. */\n focusDistanceM: number;\n /** Subject-plane distance from the lens plane in metres. */\n subjectDistanceM: number;\n}\n\nexport interface DefocusCircle {\n /** Geometric blur-circle diameter at the sensor plane in millimetres. */\n diameterMm: number;\n}\n\n/**\n * Calculates the geometric defocus-circle diameter at the sensor plane for a\n * subject plane away from the selected focus plane, using the stable closed\n * form c = f^2 |s - d| / (N d (s - f)) (model 1.1.0).\n *\n * @param input Lens, aperture, focus-plane, and subject-plane distances.\n * @returns Geometric blur-circle diameter.\n */\nexport function calculateDefocusCircle(\n input: CalculateDefocusCircleInput\n): CalculationResult<DefocusCircle> {\n requireInputKeys(input, \"calculateDefocusCircle\", [\"focalLengthMm\", \"aperture\", \"focusDistanceM\", \"subjectDistanceM\"]);\n return calculateDefocusCircleUsingFocusProjection(input);\n}\n\n/** @internal Immutable identity for one request. Not a public cache or API. */\nexport interface ResolvedDefocusFocusProjection {\n readonly focalLengthMm: number;\n readonly focusDistanceM: number;\n readonly imageDistanceMm: number;\n}\n\n/** @internal Reuses a projection already calculated for this exact POC request. */\nexport function calculateDefocusCircleUsingFocusProjection(\n input: CalculateDefocusCircleInput,\n projection?: ResolvedDefocusFocusProjection\n): CalculationResult<DefocusCircle> {\n requirePositiveFinite(\"focalLengthMm\", input.focalLengthMm);\n requirePositiveFinite(\"aperture\", input.aperture);\n requirePositiveFinite(\"focusDistanceM\", input.focusDistanceM);\n requirePositiveFinite(\"subjectDistanceM\", input.subjectDistanceM);\n\n let focusImageDistanceMm: number;\n let subjectImageDistanceMm: number;\n try {\n if (projection !== undefined) {\n if (projection.focalLengthMm !== input.focalLengthMm ||\n projection.focusDistanceM !== input.focusDistanceM ||\n input.focusDistanceM * 1000 <= input.focalLengthMm) {\n throw new InvalidScientificInputError(\"Resolved focus projection identity differs from the request.\");\n }\n requirePositiveFinite(\"resolvedFocusImageDistanceMm\", projection.imageDistanceMm);\n focusImageDistanceMm = projection.imageDistanceMm;\n } else {\n focusImageDistanceMm = calculateThinLensImageDistance({\n focalLengthMm: input.focalLengthMm,\n objectDistanceM: input.focusDistanceM\n }).value.imageDistanceMm;\n }\n subjectImageDistanceMm = calculateThinLensImageDistance({\n focalLengthMm: input.focalLengthMm,\n objectDistanceM: input.subjectDistanceM\n }).value.imageDistanceMm;\n } catch (error) {\n if (error instanceof InvalidScientificInputError) {\n throw new InvalidScientificInputError(\n \"focusDistanceM and subjectDistanceM must be beyond the focal length.\"\n );\n }\n throw error;\n }\n // Both image distances are still resolved above, so the thin-lens domain checks\n // and the reused-projection identity check still run.\n void focusImageDistanceMm;\n void subjectImageDistanceMm;\n const apertureDiameterMm = input.focalLengthMm / input.aperture;\n const focusDistanceMm = input.focusDistanceM * 1000;\n const subjectDistanceMm = input.subjectDistanceM * 1000;\n\n // Closed form of D |v_d - v_s| / v_d with v = f x / (x - f) (Gaussian thin lens):\n // c = f^2 |s - d| / (N d (s - f)).\n // It avoids subtracting two nearly equal image distances (catastrophic\n // cancellation for distant subjects) and is grouped as bounded ratios so the\n // intermediate products cannot overflow for finite in-domain inputs.\n const diameterMm =\n apertureDiameterMm *\n (Math.abs(focusDistanceMm - subjectDistanceMm) / subjectDistanceMm) *\n (input.focalLengthMm / (focusDistanceMm - input.focalLengthMm));\n\n return calculatedResult(\n { diameterMm },\n \"thin-lens-defocus-circle\",\n \"1.1.0\",\n [\"Geometric thin-lens model\", \"Ideal circular entrance pupil\"]\n );\n}\n"]}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds a `LensSampledPsfProfile` for an ideal, aberration-free, in-focus lens with a uniformly lit
|
|
3
|
+
* circular pupil: the Airy pattern of scalar Fraunhofer diffraction, one unit-sum kernel per declared
|
|
4
|
+
* wavelength on ONE shared sample grid (2.1.0).
|
|
5
|
+
*
|
|
6
|
+
* **Model.** The pupil diameter is D = f/N (entrance pupil = exit pupil, unity pupil magnification) and
|
|
7
|
+
* the pupil-to-image distance z is the thin-lens image distance for the focus (f at infinity), so the
|
|
8
|
+
* image-side (working) f-number is N_w = z/D. The incoherent optical transfer function (OTF) of a
|
|
9
|
+
* uniform circular pupil is the normalized autocorrelation of the pupil,
|
|
10
|
+
* H(ρ) = (2/π)·(acos ρ − ρ·√(1 − ρ²)), ρ = |f|/f_c ≤ 1, f_c = 1/(λ·N_w),
|
|
11
|
+
* and the intensity PSF is its inverse Fourier transform (the Airy pattern, first zero at 1.21967·λ·N_w)
|
|
12
|
+
* (MIT OpenCourseWare 2.71 Optics, Spring 2009, lectures 21–22, free: the intensity PSF as the transform of
|
|
13
|
+
* the pupil autocorrelation and the circular-pupil MTF; also see: Goodman, Introduction to Fourier Optics,
|
|
14
|
+
* 4th ed., 2017, §6.3).
|
|
15
|
+
*
|
|
16
|
+
* **Cell integration (exact, no Bessel functions).** Kernel sample (i, j) is the PSF energy inside the
|
|
17
|
+
* square cell of side p centred on (i·p, j·p). The cell integral is the PSF convolved with the cell's
|
|
18
|
+
* indicator, evaluated at the cell centre, so in the frequency domain
|
|
19
|
+
* K(i, j) = p² ∫∫ H(|f|/f_c)·sinc(p·f_x)·sinc(p·f_y)·cos(2π·p·i·f_x)·cos(2π·p·j·f_y) d²f,
|
|
20
|
+
* with sinc(x) = sin(πx)/(πx) (the sine terms vanish because H is even). It is evaluated in polar
|
|
21
|
+
* coordinates: a trapezoid rule in angle (exponentially convergent for this smooth periodic integrand) and
|
|
22
|
+
* Gauss–Legendre in t with ρ = 1 − t², which removes the (1 − ρ)^{3/2} edge behaviour of H. The node counts
|
|
23
|
+
* follow from the integrand's bandwidth with a fixed margin; the tests check convergence by doubling them and
|
|
24
|
+
* check the values against an independent real-space integration of `calculateIdealPolygonDiffractionPsf` in
|
|
25
|
+
* its many-blade (circular) limit. The sum of all cells is exactly 1 (Parseval), so the energy captured by
|
|
26
|
+
* the finite kernel is Σ K over its window and the truncated energy is 1 − Σ K.
|
|
27
|
+
*
|
|
28
|
+
* **Truncation and normalization.** The kernel is the (2R+1)² window of cells. The Airy tails fall only as
|
|
29
|
+
* r⁻³, so a finite window always misses some energy: it is reported per wavelength, and the window is then
|
|
30
|
+
* renormalized to unit sum because the sampled-profile contract requires unit-energy kernels. The missing
|
|
31
|
+
* tail energy is thereby put back inside the window (an approximation that slightly raises low-frequency
|
|
32
|
+
* contrast compared with the untruncated pattern).
|
|
33
|
+
*
|
|
34
|
+
* **Approximations (labelled):** scalar (no polarization), aberration-free, uniform pupil amplitude, exactly in
|
|
35
|
+
* focus (no defocus), thin lens with unity pupil magnification, the on-axis PSF used across the declared field
|
|
36
|
+
* (isoplanatic), PSF energy binned into the sample cells, finite window renormalized. Not a measured lens.
|
|
37
|
+
* @see docs/PSF_FOUNDATION.md, "Diffraction-limited sampled profile (2.1)".
|
|
38
|
+
*/
|
|
39
|
+
import { type CalculationResult } from "../core/calculation-result.js";
|
|
40
|
+
import type { FocusPlane } from "./focus-state.js";
|
|
41
|
+
import { type LensSampledPsfProfile } from "./lens-psf-profile.js";
|
|
42
|
+
export declare const DIFFRACTION_LIMITED_PSF_PROFILE_MODEL: Readonly<{
|
|
43
|
+
modelId: "photivra-diffraction-limited-circular-pupil-psf";
|
|
44
|
+
modelVersion: "1.0.0";
|
|
45
|
+
}>;
|
|
46
|
+
/** Input limits: at most 64 wavelengths, kernel radius 0–32 samples (the irradiance-convolution limit). */
|
|
47
|
+
export declare const DIFFRACTION_LIMITED_PSF_PROFILE_LIMITS: Readonly<{
|
|
48
|
+
maximumWavelengths: 64;
|
|
49
|
+
maximumKernelRadiusSamples: 32;
|
|
50
|
+
}>;
|
|
51
|
+
export interface CreateDiffractionLimitedPsfProfileInput {
|
|
52
|
+
/** Only `circular` in 2.1.0 (polygon pupils: `calculateIdealPolygonDiffractionPsf` gives point densities). */
|
|
53
|
+
aperture: "circular";
|
|
54
|
+
focalLengthMm: number;
|
|
55
|
+
apertureFNumber: number;
|
|
56
|
+
focus: FocusPlane;
|
|
57
|
+
/** Strictly increasing wavelengths, nm, in the medium of propagation (no air/vacuum conversion is applied). 1–64. */
|
|
58
|
+
wavelengthsNm: readonly number[];
|
|
59
|
+
/** Square sample pitch of every kernel, µm. */
|
|
60
|
+
samplePitchMicrometers: number;
|
|
61
|
+
/** Kernel half-width in samples; each kernel is (2R + 1)². 0–32. */
|
|
62
|
+
kernelRadiusSamples: number;
|
|
63
|
+
/** Half-extent of the image field over which the on-axis PSF is declared (profile field axes ±x, ±y), mm. */
|
|
64
|
+
fieldHalfExtentMm: {
|
|
65
|
+
x: number;
|
|
66
|
+
y: number;
|
|
67
|
+
};
|
|
68
|
+
profileId: string;
|
|
69
|
+
}
|
|
70
|
+
export interface DiffractionLimitedPsfWavelength {
|
|
71
|
+
wavelengthNm: number;
|
|
72
|
+
/** f_c = 1/(λ·N_w), cycles per µm. */
|
|
73
|
+
cutoffFrequencyCyclesPerMicrometer: number;
|
|
74
|
+
/** 1.21967·λ·N_w, µm. */
|
|
75
|
+
firstZeroRadiusMicrometers: number;
|
|
76
|
+
/** Σ of the cell energies inside the window before renormalization (of a total of 1). */
|
|
77
|
+
capturedEnergyFraction: number;
|
|
78
|
+
/** 1 − capturedEnergyFraction: the Airy tail energy outside the window, put back by renormalization. */
|
|
79
|
+
truncatedEnergyFraction: number;
|
|
80
|
+
/** Fraction of the renormalized kernel in the centre sample. */
|
|
81
|
+
centreSampleFraction: number;
|
|
82
|
+
}
|
|
83
|
+
export interface DiffractionLimitedPsfProfile {
|
|
84
|
+
profile: LensSampledPsfProfile;
|
|
85
|
+
model: typeof DIFFRACTION_LIMITED_PSF_PROFILE_MODEL;
|
|
86
|
+
pupilDiameterMm: number;
|
|
87
|
+
pupilToImageDistanceMm: number;
|
|
88
|
+
workingFNumber: number;
|
|
89
|
+
kernelRadiusSamples: number;
|
|
90
|
+
samplePitchMicrometers: number;
|
|
91
|
+
wavelengths: readonly DiffractionLimitedPsfWavelength[];
|
|
92
|
+
/** Largest truncated energy over the wavelengths. */
|
|
93
|
+
maximumTruncatedEnergyFraction: number;
|
|
94
|
+
quadrature: {
|
|
95
|
+
method: "polar-frequency-domain-trapezoid-gauss-legendre";
|
|
96
|
+
maximumRadialNodes: number;
|
|
97
|
+
maximumAngularNodes: number;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Cell energies K(i, j), 0 ≤ i, j ≤ R, of the Airy pattern for β = p·f_c (cell side in units of the cut-off
|
|
102
|
+
* period). `scale` multiplies the node counts (1 in production; the tests use 2 to check convergence).
|
|
103
|
+
*/
|
|
104
|
+
export declare function calculateAiryCellEnergies(beta: number, radius: number, scale?: number): {
|
|
105
|
+
cells: Float64Array;
|
|
106
|
+
radialNodes: number;
|
|
107
|
+
angularNodes: number;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Creates a sampled lens PSF profile for an ideal diffraction-limited lens with a circular pupil: one
|
|
111
|
+
* unit-sum Airy kernel per wavelength on one shared (2R+1)² grid, with the truncated energy reported per
|
|
112
|
+
* wavelength. The profile declares the given focal length, f-number and focus exactly, and the field axes
|
|
113
|
+
* ±`fieldHalfExtentMm` with the same kernel at every field node.
|
|
114
|
+
* @param input - See `CreateDiffractionLimitedPsfProfileInput`.
|
|
115
|
+
* @returns The profile and its diffraction record. An approximation; not a measured lens.
|
|
116
|
+
* @see docs/PSF_FOUNDATION.md, "Diffraction-limited sampled profile (2.1)".
|
|
117
|
+
*/
|
|
118
|
+
export declare function createDiffractionLimitedPsfProfile(input: CreateDiffractionLimitedPsfProfileInput): CalculationResult<DiffractionLimitedPsfProfile>;
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* Builds a `LensSampledPsfProfile` for an ideal, aberration-free, in-focus lens with a uniformly lit
|
|
4
|
+
* circular pupil: the Airy pattern of scalar Fraunhofer diffraction, one unit-sum kernel per declared
|
|
5
|
+
* wavelength on ONE shared sample grid (2.1.0).
|
|
6
|
+
*
|
|
7
|
+
* **Model.** The pupil diameter is D = f/N (entrance pupil = exit pupil, unity pupil magnification) and
|
|
8
|
+
* the pupil-to-image distance z is the thin-lens image distance for the focus (f at infinity), so the
|
|
9
|
+
* image-side (working) f-number is N_w = z/D. The incoherent optical transfer function (OTF) of a
|
|
10
|
+
* uniform circular pupil is the normalized autocorrelation of the pupil,
|
|
11
|
+
* H(ρ) = (2/π)·(acos ρ − ρ·√(1 − ρ²)), ρ = |f|/f_c ≤ 1, f_c = 1/(λ·N_w),
|
|
12
|
+
* and the intensity PSF is its inverse Fourier transform (the Airy pattern, first zero at 1.21967·λ·N_w)
|
|
13
|
+
* (MIT OpenCourseWare 2.71 Optics, Spring 2009, lectures 21–22, free: the intensity PSF as the transform of
|
|
14
|
+
* the pupil autocorrelation and the circular-pupil MTF; also see: Goodman, Introduction to Fourier Optics,
|
|
15
|
+
* 4th ed., 2017, §6.3).
|
|
16
|
+
*
|
|
17
|
+
* **Cell integration (exact, no Bessel functions).** Kernel sample (i, j) is the PSF energy inside the
|
|
18
|
+
* square cell of side p centred on (i·p, j·p). The cell integral is the PSF convolved with the cell's
|
|
19
|
+
* indicator, evaluated at the cell centre, so in the frequency domain
|
|
20
|
+
* K(i, j) = p² ∫∫ H(|f|/f_c)·sinc(p·f_x)·sinc(p·f_y)·cos(2π·p·i·f_x)·cos(2π·p·j·f_y) d²f,
|
|
21
|
+
* with sinc(x) = sin(πx)/(πx) (the sine terms vanish because H is even). It is evaluated in polar
|
|
22
|
+
* coordinates: a trapezoid rule in angle (exponentially convergent for this smooth periodic integrand) and
|
|
23
|
+
* Gauss–Legendre in t with ρ = 1 − t², which removes the (1 − ρ)^{3/2} edge behaviour of H. The node counts
|
|
24
|
+
* follow from the integrand's bandwidth with a fixed margin; the tests check convergence by doubling them and
|
|
25
|
+
* check the values against an independent real-space integration of `calculateIdealPolygonDiffractionPsf` in
|
|
26
|
+
* its many-blade (circular) limit. The sum of all cells is exactly 1 (Parseval), so the energy captured by
|
|
27
|
+
* the finite kernel is Σ K over its window and the truncated energy is 1 − Σ K.
|
|
28
|
+
*
|
|
29
|
+
* **Truncation and normalization.** The kernel is the (2R+1)² window of cells. The Airy tails fall only as
|
|
30
|
+
* r⁻³, so a finite window always misses some energy: it is reported per wavelength, and the window is then
|
|
31
|
+
* renormalized to unit sum because the sampled-profile contract requires unit-energy kernels. The missing
|
|
32
|
+
* tail energy is thereby put back inside the window (an approximation that slightly raises low-frequency
|
|
33
|
+
* contrast compared with the untruncated pattern).
|
|
34
|
+
*
|
|
35
|
+
* **Approximations (labelled):** scalar (no polarization), aberration-free, uniform pupil amplitude, exactly in
|
|
36
|
+
* focus (no defocus), thin lens with unity pupil magnification, the on-axis PSF used across the declared field
|
|
37
|
+
* (isoplanatic), PSF energy binned into the sample cells, finite window renormalized. Not a measured lens.
|
|
38
|
+
* @see docs/PSF_FOUNDATION.md, "Diffraction-limited sampled profile (2.1)".
|
|
39
|
+
*/
|
|
40
|
+
import { approximationResult } from "../core/calculation-result.js";
|
|
41
|
+
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
42
|
+
import { requireAllowlistedRecord } from "../core/record-validation.js";
|
|
43
|
+
import { calculateThinLensImageDistance } from "./thin-lens.js";
|
|
44
|
+
import { parseLensSampledPsfProfile } from "./lens-psf-profile.js";
|
|
45
|
+
export const DIFFRACTION_LIMITED_PSF_PROFILE_MODEL = Object.freeze({
|
|
46
|
+
modelId: "photivra-diffraction-limited-circular-pupil-psf", modelVersion: "1.0.0"
|
|
47
|
+
});
|
|
48
|
+
/** Input limits: at most 64 wavelengths, kernel radius 0–32 samples (the irradiance-convolution limit). */
|
|
49
|
+
export const DIFFRACTION_LIMITED_PSF_PROFILE_LIMITS = Object.freeze({ maximumWavelengths: 64, maximumKernelRadiusSamples: 32 });
|
|
50
|
+
/** Radius of the first dark ring of the Airy pattern in units of λ·N_w: j₁,₁/π, j₁,₁ = 3.8317059702 (first zero of J₁). */
|
|
51
|
+
const AIRY_FIRST_ZERO_PER_LAMBDA_N = 3.8317059702075125 / Math.PI;
|
|
52
|
+
const EVIDENCE = Object.freeze([Object.freeze({ sourceOrigin: "photivra",
|
|
53
|
+
sourceReference: "photivra:diffraction-limited-psf-profile", reuseStatus: "photivra-owned" })]);
|
|
54
|
+
const LIMITATIONS = Object.freeze([
|
|
55
|
+
"Scalar Fraunhofer diffraction of an ideal, uniformly lit circular pupil (Airy pattern); no aberration, apodization, polarization or stray light.",
|
|
56
|
+
"Exactly in focus: no defocus or depth of field. Thin lens with unity pupil magnification; the pupil-to-image distance is the thin-lens image distance.",
|
|
57
|
+
"The on-axis PSF is declared unchanged across the field (isoplanatic); no field-dependent aberration or pupil clipping.",
|
|
58
|
+
"PSF energy is binned into square sample cells; the finite window misses the Airy tail energy listed per wavelength and is renormalized to unit sum.",
|
|
59
|
+
"Wavelengths are used as given, in the declared basis, without air/vacuum conversion."
|
|
60
|
+
]);
|
|
61
|
+
function positive(value, name) {
|
|
62
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0)
|
|
63
|
+
throw new InvalidConfigurationError(name + " must be a positive finite number.");
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
/** Gauss–Legendre nodes and weights on [0, 1] (Newton iteration on Pₙ; DLMF §3.5(v)). Cached per n. */
|
|
67
|
+
const GAUSS_LEGENDRE = new Map();
|
|
68
|
+
function gaussLegendre(n) {
|
|
69
|
+
const cached = GAUSS_LEGENDRE.get(n);
|
|
70
|
+
if (cached)
|
|
71
|
+
return cached;
|
|
72
|
+
const nodes = new Float64Array(n), weights = new Float64Array(n);
|
|
73
|
+
for (let k = 0; k < Math.ceil(n / 2); k++) {
|
|
74
|
+
let x = Math.cos(Math.PI * (k + 0.75) / (n + 0.5));
|
|
75
|
+
for (let iteration = 0; iteration < 100; iteration++) {
|
|
76
|
+
let p0 = 1, p1 = x;
|
|
77
|
+
for (let m = 2; m <= n; m++) {
|
|
78
|
+
const p2 = ((2 * m - 1) * x * p1 - (m - 1) * p0) / m;
|
|
79
|
+
p0 = p1;
|
|
80
|
+
p1 = p2;
|
|
81
|
+
}
|
|
82
|
+
const step = p1 / (n * (x * p1 - p0) / (x * x - 1));
|
|
83
|
+
x -= step;
|
|
84
|
+
if (Math.abs(step) < 1e-16)
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
let p0 = 1, p1 = x;
|
|
88
|
+
for (let m = 2; m <= n; m++) {
|
|
89
|
+
const p2 = ((2 * m - 1) * x * p1 - (m - 1) * p0) / m;
|
|
90
|
+
p0 = p1;
|
|
91
|
+
p1 = p2;
|
|
92
|
+
}
|
|
93
|
+
const derivative = n * (x * p1 - p0) / (x * x - 1);
|
|
94
|
+
const w = 1 / ((1 - x * x) * derivative * derivative);
|
|
95
|
+
// Map [-1, 1] to [0, 1]: t = (1 ± x)/2, weight w (2/(1-x²)P'² halved).
|
|
96
|
+
nodes[k] = (1 - x) / 2;
|
|
97
|
+
weights[k] = w;
|
|
98
|
+
nodes[n - 1 - k] = (1 + x) / 2;
|
|
99
|
+
weights[n - 1 - k] = w;
|
|
100
|
+
}
|
|
101
|
+
const result = { nodes, weights };
|
|
102
|
+
if (GAUSS_LEGENDRE.size < 64)
|
|
103
|
+
GAUSS_LEGENDRE.set(n, result);
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
function sinc(x) {
|
|
107
|
+
if (x === 0)
|
|
108
|
+
return 1;
|
|
109
|
+
const a = Math.PI * x;
|
|
110
|
+
return Math.sin(a) / a;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Cell energies K(i, j), 0 ≤ i, j ≤ R, of the Airy pattern for β = p·f_c (cell side in units of the cut-off
|
|
114
|
+
* period). `scale` multiplies the node counts (1 in production; the tests use 2 to check convergence).
|
|
115
|
+
*/
|
|
116
|
+
export function calculateAiryCellEnergies(beta, radius, scale = 1) {
|
|
117
|
+
// Bandwidth of the angular and radial integrands: c = π·β·(2R + 1)·√2 (the sinc factors and the highest cosine).
|
|
118
|
+
const c = Math.PI * beta * (2 * radius + 1) * Math.SQRT2, margin = 10 * Math.cbrt(c) + 24;
|
|
119
|
+
const quarter = Math.ceil(scale * (c + margin) / 4), radialNodes = Math.ceil(scale * (c + margin));
|
|
120
|
+
const { nodes, weights } = gaussLegendre(radialNodes), size = radius + 1, cells = new Float64Array(size * size);
|
|
121
|
+
const ca = new Float64Array(size), cb = new Float64Array(size), angularStep = (Math.PI / 2) / quarter;
|
|
122
|
+
for (let r = 0; r < radialNodes; r++) {
|
|
123
|
+
const t = nodes[r], rho = 1 - t * t;
|
|
124
|
+
// H(1 − t²) without cancellation: acos(1 − t²) = 2·asin(t/√2), ρ·√(1 − ρ²) = ρ·t·√(2 − t²).
|
|
125
|
+
const otf = (2 / Math.PI) * (2 * Math.asin(t / Math.SQRT2) - rho * t * Math.sqrt(2 - t * t));
|
|
126
|
+
// ∫₀¹ g(ρ) dρ = ∫₀¹ g(1 − t²)·2t dt; the 4 is the four symmetric quadrants of the angular trapezoid.
|
|
127
|
+
const radialWeight = weights[r] * 2 * t * rho * otf * 4 * angularStep;
|
|
128
|
+
for (let k = 0; k <= quarter; k++) {
|
|
129
|
+
const theta = k * angularStep, x = beta * rho * Math.cos(theta), y = beta * rho * Math.sin(theta);
|
|
130
|
+
const w = radialWeight * (k === 0 || k === quarter ? 0.5 : 1) * sinc(x) * sinc(y);
|
|
131
|
+
// cos(2π·i·x) and cos(2π·j·y) by the Chebyshev recurrence.
|
|
132
|
+
const cx = Math.cos(2 * Math.PI * x), cy = Math.cos(2 * Math.PI * y);
|
|
133
|
+
ca[0] = 1;
|
|
134
|
+
cb[0] = 1;
|
|
135
|
+
if (size > 1) {
|
|
136
|
+
ca[1] = cx;
|
|
137
|
+
cb[1] = cy;
|
|
138
|
+
}
|
|
139
|
+
for (let i = 2; i < size; i++) {
|
|
140
|
+
ca[i] = 2 * cx * ca[i - 1] - ca[i - 2];
|
|
141
|
+
cb[i] = 2 * cy * cb[i - 1] - cb[i - 2];
|
|
142
|
+
}
|
|
143
|
+
for (let j = 0; j < size; j++) {
|
|
144
|
+
const wj = w * cb[j];
|
|
145
|
+
for (let i = 0; i < size; i++) {
|
|
146
|
+
const o = j * size + i;
|
|
147
|
+
cells[o] = cells[o] + wj * ca[i];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const area = beta * beta;
|
|
153
|
+
for (let i = 0; i < cells.length; i++)
|
|
154
|
+
cells[i] = cells[i] * area;
|
|
155
|
+
return { cells, radialNodes, angularNodes: 4 * quarter };
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Creates a sampled lens PSF profile for an ideal diffraction-limited lens with a circular pupil: one
|
|
159
|
+
* unit-sum Airy kernel per wavelength on one shared (2R+1)² grid, with the truncated energy reported per
|
|
160
|
+
* wavelength. The profile declares the given focal length, f-number and focus exactly, and the field axes
|
|
161
|
+
* ±`fieldHalfExtentMm` with the same kernel at every field node.
|
|
162
|
+
* @param input - See `CreateDiffractionLimitedPsfProfileInput`.
|
|
163
|
+
* @returns The profile and its diffraction record. An approximation; not a measured lens.
|
|
164
|
+
* @see docs/PSF_FOUNDATION.md, "Diffraction-limited sampled profile (2.1)".
|
|
165
|
+
*/
|
|
166
|
+
export function createDiffractionLimitedPsfProfile(input) {
|
|
167
|
+
const r = requireAllowlistedRecord(input, ["aperture", "focalLengthMm", "apertureFNumber", "focus", "wavelengthsNm", "samplePitchMicrometers",
|
|
168
|
+
"kernelRadiusSamples", "fieldHalfExtentMm", "profileId"], "Invalid diffraction-limited PSF profile input.");
|
|
169
|
+
if (r.aperture !== "circular")
|
|
170
|
+
throw new InvalidConfigurationError("aperture must be \"circular\".");
|
|
171
|
+
const focalLengthMm = positive(r.focalLengthMm, "focalLengthMm"), fNumber = positive(r.apertureFNumber, "apertureFNumber");
|
|
172
|
+
const pitch = positive(r.samplePitchMicrometers, "samplePitchMicrometers");
|
|
173
|
+
const L = DIFFRACTION_LIMITED_PSF_PROFILE_LIMITS;
|
|
174
|
+
const radius = r.kernelRadiusSamples;
|
|
175
|
+
if (typeof radius !== "number" || !Number.isSafeInteger(radius) || radius < 0 || radius > L.maximumKernelRadiusSamples) {
|
|
176
|
+
throw new InvalidConfigurationError("kernelRadiusSamples must be an integer from 0 to " + L.maximumKernelRadiusSamples + ".");
|
|
177
|
+
}
|
|
178
|
+
const focus = requireAllowlistedRecord(r.focus, ["kind", "distanceM"], "Invalid focus.");
|
|
179
|
+
let focusDiopters, distanceMm;
|
|
180
|
+
if (focus.kind === "infinity") {
|
|
181
|
+
if (focus.distanceM !== undefined)
|
|
182
|
+
throw new InvalidConfigurationError("An infinity focus has no distanceM.");
|
|
183
|
+
focusDiopters = 0;
|
|
184
|
+
distanceMm = focalLengthMm;
|
|
185
|
+
}
|
|
186
|
+
else if (focus.kind === "finite") {
|
|
187
|
+
const distanceM = positive(focus.distanceM, "focus.distanceM");
|
|
188
|
+
focusDiopters = 1 / distanceM;
|
|
189
|
+
distanceMm = calculateThinLensImageDistance({ focalLengthMm, objectDistanceM: distanceM }).value.imageDistanceMm;
|
|
190
|
+
}
|
|
191
|
+
else
|
|
192
|
+
throw new InvalidConfigurationError("focus.kind must be finite or infinity.");
|
|
193
|
+
const field = requireAllowlistedRecord(r.fieldHalfExtentMm, ["x", "y"], "Invalid fieldHalfExtentMm.");
|
|
194
|
+
const fieldX = positive(field.x, "fieldHalfExtentMm.x"), fieldY = positive(field.y, "fieldHalfExtentMm.y");
|
|
195
|
+
const list = r.wavelengthsNm;
|
|
196
|
+
if (!Array.isArray(list) || list.length < 1 || list.length > L.maximumWavelengths)
|
|
197
|
+
throw new InvalidConfigurationError("wavelengthsNm must list 1 to 64 wavelengths.");
|
|
198
|
+
const wavelengths = list.map((value, index) => positive(value, "wavelengthsNm[" + index + "]"));
|
|
199
|
+
for (let i = 1; i < wavelengths.length; i++)
|
|
200
|
+
if (!(wavelengths[i] > wavelengths[i - 1]))
|
|
201
|
+
throw new InvalidConfigurationError("wavelengthsNm must be strictly increasing.");
|
|
202
|
+
if (typeof r.profileId !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(r.profileId))
|
|
203
|
+
throw new InvalidConfigurationError("profileId must be a public opaque ID.");
|
|
204
|
+
const pupilDiameterMm = focalLengthMm / fNumber, workingFNumber = distanceMm / pupilDiameterMm, size = 2 * radius + 1;
|
|
205
|
+
let maximumRadialNodes = 0, maximumAngularNodes = 0, maximumTruncated = 0;
|
|
206
|
+
const records = [], kernels = [];
|
|
207
|
+
for (const nm of wavelengths) {
|
|
208
|
+
const lambdaN = nm / 1000 * workingFNumber, cutoff = 1 / lambdaN;
|
|
209
|
+
const airy = calculateAiryCellEnergies(pitch * cutoff, radius);
|
|
210
|
+
maximumRadialNodes = Math.max(maximumRadialNodes, airy.radialNodes);
|
|
211
|
+
maximumAngularNodes = Math.max(maximumAngularNodes, airy.angularNodes);
|
|
212
|
+
const values = new Array(size * size);
|
|
213
|
+
let captured = 0;
|
|
214
|
+
for (let ky = 0; ky < size; ky++)
|
|
215
|
+
for (let kx = 0; kx < size; kx++) {
|
|
216
|
+
const value = airy.cells[Math.abs(ky - radius) * (radius + 1) + Math.abs(kx - radius)];
|
|
217
|
+
// Every cell energy of a non-negative PSF is positive; a negative value would be a quadrature failure.
|
|
218
|
+
if (!(value > -1e-13))
|
|
219
|
+
throw new InvalidConfigurationError("Diffraction cell integration failed to converge.");
|
|
220
|
+
values[ky * size + kx] = Math.max(0, value);
|
|
221
|
+
captured += values[ky * size + kx];
|
|
222
|
+
}
|
|
223
|
+
if (!(captured > 0 && captured <= 1 + 1e-9))
|
|
224
|
+
throw new InvalidConfigurationError("Diffraction cell integration failed to converge.");
|
|
225
|
+
const truncated = Math.max(0, 1 - captured);
|
|
226
|
+
maximumTruncated = Math.max(maximumTruncated, truncated);
|
|
227
|
+
const kernel = values.map((v) => v / captured);
|
|
228
|
+
kernels.push(kernel);
|
|
229
|
+
records.push({ wavelengthNm: nm, cutoffFrequencyCyclesPerMicrometer: cutoff, firstZeroRadiusMicrometers: AIRY_FIRST_ZERO_PER_LAMBDA_N * lambdaN,
|
|
230
|
+
capturedEnergyFraction: captured, truncatedEnergyFraction: truncated, centreSampleFraction: kernel[radius * size + radius] });
|
|
231
|
+
}
|
|
232
|
+
const uncertainty = { kind: "not-quantified", limitation: "Ideal diffraction-limited model; no measured lens or quadrature error bound." };
|
|
233
|
+
const nodes = [-fieldX, fieldX].flatMap((fx) => [-fieldY, fieldY].flatMap((fy) => wavelengths.map((nm, index) => ({
|
|
234
|
+
nodeId: "airy-" + (fx < 0 ? "xm" : "xp") + "-" + (fy < 0 ? "ym" : "yp") + "-" + index,
|
|
235
|
+
coordinate: { focalLengthMm, focusDiopters, apertureFNumber: fNumber, fieldXmm: fx, fieldYmm: fy, wavelengthNm: nm, signedDefocusImagePlaneMicrometers: 0 },
|
|
236
|
+
kernel: { widthSamples: size, heightSamples: size, samplePitchMicrometersX: pitch, samplePitchMicrometersY: pitch, centerSampleX: radius, centerSampleY: radius,
|
|
237
|
+
normalizedIntensity: kernels[index] },
|
|
238
|
+
bestFocusImagePlaneOffsetMicrometers: 0, relativePupilThroughputFactor: 1, evidence: EVIDENCE, uncertainty
|
|
239
|
+
}))));
|
|
240
|
+
const profile = parseLensSampledPsfProfile({ schemaVersion: "0.1.0", profileId: r.profileId, profileVersion: DIFFRACTION_LIMITED_PSF_PROFILE_MODEL.modelVersion,
|
|
241
|
+
scientificStatus: "approximation", opticalDomain: "lens-primary-optical-path-only", coordinateSystem: "image-plane-metric", fieldAxes: "+X right, +Y up",
|
|
242
|
+
kernelEnergyNormalization: "unit-energy-shape", interpolation: "bounded-regular-grid-multilinear", throughputOwnership: "separate-relative-pupil-throughput-factor",
|
|
243
|
+
responseIncludes: { diffraction: true, aberration: false, defocus: false, pupilClippingShape: false },
|
|
244
|
+
sensorOpticalStackIncluded: false, sensorSamplingIncluded: false, reconstructionIncluded: false, strayLightIncluded: false,
|
|
245
|
+
axes: { focalLengthMm: [focalLengthMm], focusDiopters: [focusDiopters], apertureFNumber: [fNumber], fieldXmm: [-fieldX, fieldX], fieldYmm: [-fieldY, fieldY],
|
|
246
|
+
wavelengthNm: wavelengths, signedDefocusImagePlaneMicrometers: [0] },
|
|
247
|
+
nodes, evidence: EVIDENCE, limitations: [...LIMITATIONS] });
|
|
248
|
+
return approximationResult({ profile, model: DIFFRACTION_LIMITED_PSF_PROFILE_MODEL, pupilDiameterMm, pupilToImageDistanceMm: distanceMm, workingFNumber,
|
|
249
|
+
kernelRadiusSamples: radius, samplePitchMicrometers: pitch, wavelengths: records, maximumTruncatedEnergyFraction: maximumTruncated,
|
|
250
|
+
quadrature: { method: "polar-frequency-domain-trapezoid-gauss-legendre", maximumRadialNodes, maximumAngularNodes } }, DIFFRACTION_LIMITED_PSF_PROFILE_MODEL.modelId, DIFFRACTION_LIMITED_PSF_PROFILE_MODEL.modelVersion, [...LIMITATIONS]);
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=diffraction-psf-profile.js.map
|