@photivra/engine 2.13.0 → 2.14.1
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 +75 -1
- package/CITATION.cff +1 -1
- package/NOTICE +5 -4
- package/README.md +10 -8
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +16 -10
- package/dist/camera/lens-projection.js +2 -1
- package/dist/camera/lens-projection.js.map +1 -1
- package/dist/capture/dng-import.js +1 -1
- package/dist/capture/dng-import.js.map +1 -1
- package/dist/capture/host-yield-cadence.js +1 -1
- package/dist/capture/host-yield-cadence.js.map +1 -1
- package/dist/capture/native-environment-optical-stage.js +1 -1
- package/dist/capture/native-environment-optical-stage.js.map +1 -1
- package/dist/capture/native-raw.js +1 -1
- package/dist/capture/native-raw.js.map +1 -1
- package/dist/capture/packed-sensor-raw.js +3 -3
- package/dist/capture/packed-sensor-raw.js.map +1 -1
- package/dist/capture/sensor-raw-producer.js +1 -1
- package/dist/capture/sensor-raw-producer.js.map +1 -1
- package/dist/color/capture-color.js +3 -3
- package/dist/color/capture-color.js.map +1 -1
- package/dist/color/chromatic-adaptation.js +2 -2
- package/dist/color/chromatic-adaptation.js.map +1 -1
- package/dist/color/color-matching-functions.js +1 -1
- package/dist/color/color-matching-functions.js.map +1 -1
- package/dist/color/colorimetry-math.js +2 -2
- package/dist/color/colorimetry-math.js.map +1 -1
- package/dist/color/illuminants.js +3 -3
- package/dist/color/illuminants.js.map +1 -1
- package/dist/color/rgb-color-spaces.js +1 -1
- package/dist/color/rgb-color-spaces.js.map +1 -1
- package/dist/color/sensor-color-development.js +1 -1
- package/dist/color/sensor-color-development.js.map +1 -1
- package/dist/core/record-validation.js +3 -3
- package/dist/core/record-validation.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/equipment/generic-prime-lenses.js +3 -3
- package/dist/equipment/generic-prime-lenses.js.map +1 -1
- package/dist/equipment/generic-tier-assets.d.ts +23 -1
- package/dist/equipment/generic-tier-assets.js +58 -30
- package/dist/equipment/generic-tier-assets.js.map +1 -1
- package/dist/equipment/generic-tier-presets.d.ts +6 -3
- package/dist/equipment/generic-tier-presets.js +26 -13
- package/dist/equipment/generic-tier-presets.js.map +1 -1
- package/dist/exposure/auto-iso-slowest-shutter.js +2 -1
- package/dist/exposure/auto-iso-slowest-shutter.js.map +1 -1
- package/dist/exposure/flash-ttl.js +1 -1
- package/dist/exposure/flash-ttl.js.map +1 -1
- package/dist/exposure/flash.js +1 -1
- package/dist/exposure/flash.js.map +1 -1
- package/dist/facade/chart-material-layers.js +2 -2
- package/dist/facade/chart-material-layers.js.map +1 -1
- package/dist/facade/chart-radiance-batch.js +1 -1
- package/dist/facade/chart-radiance-batch.js.map +1 -1
- package/dist/facade/chart-scenes.d.ts +45 -8
- package/dist/facade/chart-scenes.js +101 -44
- package/dist/facade/chart-scenes.js.map +1 -1
- package/dist/facade/color-patches.d.ts +129 -0
- package/dist/facade/color-patches.js +209 -0
- package/dist/facade/color-patches.js.map +1 -0
- package/dist/facade/display-view-gpu.js +1 -1
- package/dist/facade/display-view-gpu.js.map +1 -1
- package/dist/facade/scene-radiance.js +2 -2
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +47 -3
- package/dist/facade/simulate-capture.js +71 -22
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.js +2 -2
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.js +2 -2
- package/dist/gpu/chart-composite-gpu.js.map +1 -1
- package/dist/gpu/display-view-composite-material-module.js +1 -1
- package/dist/gpu/display-view-composite-material-module.js.map +1 -1
- package/dist/gpu/image-kernel-execution.js +2 -2
- package/dist/gpu/image-kernel-execution.js.map +1 -1
- package/dist/gpu/temporal-sum-gpu.js +23 -23
- package/dist/gpu/webgpu-runtime.js +1 -1
- package/dist/gpu/webgpu-runtime.js.map +1 -1
- package/dist/gpu/wgsl-chart-composite-kernel.js +318 -318
- package/dist/gpu/wgsl-chart-composite-kernel.js.map +1 -1
- package/dist/gpu/wgsl-chart-kernel.js +117 -117
- package/dist/gpu/wgsl-chart-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-quality-kernel.js +505 -505
- package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-speed-kernel.js +248 -248
- package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
- package/dist/gpu/wgsl-kernels.js +203 -203
- package/dist/gpu/wgsl-kernels.js.map +1 -1
- package/dist/gpu/wgsl-sensor-kernel.js +302 -302
- package/dist/gpu/wgsl-sensor-kernel.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/motion/temporal-exposure-sum.js +1 -1
- package/dist/motion/temporal-exposure-sum.js.map +1 -1
- package/dist/optics/diffraction-psf-profile.js +4 -4
- package/dist/optics/diffraction-psf-profile.js.map +1 -1
- package/dist/optics/front-of-lens-filter.js +1 -1
- package/dist/optics/front-of-lens-filter.js.map +1 -1
- package/dist/optics/irradiance-convolution.js +1 -1
- package/dist/optics/irradiance-convolution.js.map +1 -1
- package/dist/output/native-capture-sdr.js +1 -1
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/output/png-encoder.js +2 -2
- package/dist/output/png-encoder.js.map +1 -1
- package/dist/output/print-contrast-reference.js +2 -2
- package/dist/output/print-contrast-reference.js.map +1 -1
- package/dist/output/print-jpeg.js +1 -1
- package/dist/output/print-jpeg.js.map +1 -1
- package/dist/sensor/fixed-pattern-noise.js +1 -1
- package/dist/sensor/fixed-pattern-noise.js.map +1 -1
- package/dist/sensor/readout-exposure-linkage.js +1 -1
- package/dist/sensor/readout-exposure-linkage.js.map +1 -1
- package/docs/API_REFERENCE.md +29 -1
- package/docs/QUICK_START.md +40 -5
- package/docs/USAGE.md +35 -1
- package/docs/api/core-version.md +1 -1
- package/docs/api/equipment-generic-tier-assets.md +41 -1
- package/docs/api/equipment-generic-tier-presets.md +11 -3
- package/docs/api/exports.json +107 -2
- package/docs/api/facade-chart-scenes.md +36 -5
- package/docs/api/facade-color-patches.md +150 -0
- package/docs/api/facade-simulate-capture.md +52 -2
- package/llms.txt +1 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diffraction-psf-profile.js","sourceRoot":"","sources":["../../src/optics/diffraction-psf-profile.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Builds a `LensSampledPsfProfile` for an ideal, aberration-free, in-focus lens with a uniformly lit\n * circular pupil: the Airy pattern of scalar Fraunhofer diffraction, one unit-sum kernel per declared\n * wavelength on ONE shared sample grid (2.1.0).\n *\n * **Model.** The pupil diameter is D = f/N (entrance pupil = exit pupil, unity pupil magnification) and\n * the pupil-to-image distance z is the thin-lens image distance for the focus (f at infinity), so the\n * image-side (working) f-number is N_w = z/D. The incoherent optical transfer function (OTF) of a\n * uniform circular pupil is the normalized autocorrelation of the pupil,\n * H(ρ) = (2/π)·(acos ρ − ρ·√(1 − ρ²)), ρ = |f|/f_c ≤ 1, f_c = 1/(λ·N_w),\n * and the intensity PSF is its inverse Fourier transform (the Airy pattern, first zero at 1.21967·λ·N_w)\n * (MIT OpenCourseWare 2.71 Optics, Spring 2009, lectures 21–22, free: the intensity PSF as the transform of\n * the pupil autocorrelation and the circular-pupil MTF; also see: Goodman, Introduction to Fourier Optics,\n * 4th ed., 2017, §7.3).\n *\n * **Cell integration (exact, no Bessel functions).** Kernel sample (i, j) is the PSF energy inside the\n * square cell of side p centred on (i·p, j·p). The cell integral is the PSF convolved with the cell's\n * indicator, evaluated at the cell centre, so in the frequency domain\n * 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,\n * with sinc(x) = sin(πx)/(πx) (the sine terms vanish because H is even). It is evaluated in polar\n * coordinates: a trapezoid rule in angle (exponentially convergent for this smooth periodic integrand) and\n * Gauss–Legendre in t with ρ = 1 − t², which removes the (1 − ρ)^{3/2} edge behaviour of H. The node counts\n * follow from the integrand's bandwidth with a fixed margin; the tests check convergence by doubling them and\n * check the values against an independent real-space integration of `calculateIdealPolygonDiffractionPsf` in\n * its many-blade (circular) limit. The sum of all cells is exactly 1 (Parseval), so the energy captured by\n * the finite kernel is Σ K over its window and the truncated energy is 1 − Σ K.\n *\n * **Cells much larger than the pattern (2.5; threshold lowered to β = 32 after 2.8.1).** The frequency-domain node counts grow with β = p·f_c (the\n * cell side over the cut-off period), so the work grows as β². From β ≥ `AIRY_REAL_SPACE_MINIMUM_BETA` (32) the cells are\n * integrated in real space instead, with the same model and no frequency integral: the Airy encircled energy is\n * EE(r) = 1 − J₀(x)² − J₁(x)², x = π·r·f_c (it follows from J₀′ = −J₁ and J₁′ = J₀ − J₁/x, DLMF §10.6(i), free), so\n * the energy of the rectangle [0, X] × [0, Y] is (1/2π)∫ EE(r_edge(θ)) dθ over its quadrant, a one-dimensional\n * integral in θ. Every cell is a signed sum of such rectangles. J₀² + J₁² comes from the Hankel asymptotic expansion\n * (DLMF §10.17(i), eq. 10.17.3, free) from x = 300, with eight terms in each of P and Q (remainder under 1e-17,\n * DLMF §10.17(iii)), and below it from Miller's backward recurrence normalized by J₀ + 2ΣJ₂ₖ = 1 (DLMF §3.6(iii),\n * 10.12.4, free). The θ integral uses 16-point Gauss–Legendre panels on which the phase 2x changes by at most\n * 2 radians, so the work grows only as β. The tests check the two methods against each other from β = 32 to 400, the\n * real-space cells against the asymptotic leakage 8√2/(π³·β) of the centre cell, and convergence under doubled panel\n * counts. The threshold was 192 in 2.5; it moved to 32 because from there the real-space cells agree with the frequency-domain cells\n * within about 1e-12 and cost a few to a few hundred times less (a 750 µm whole-frame cell at f/8 took 3.4 s for 20\n * wavelengths). Every β a native pitch up to 10 µm reaches (at most 10/(0.38·1.4) ≈ 19) stays in the frequency domain,\n * so captures at sensor pitch are unchanged; larger cells (binned and whole-frame views) change in the last bits only.\n *\n * **Reuse (2.6).** The cells depend only on (β, R) (and the test-only node scale), so `calculateAiryCellEnergies` keeps the\n * 256 most recently used results and returns copies: tiles of one frame rendered in the same worker, and captures that\n * change only the exposure, ISO, scene or output, reuse the kernels instead of integrating them again. The frequency-domain\n * loop also takes cos θ and sin θ from a per-call table computed with the same expressions, so the values are unchanged.\n *\n * **Truncation and normalization.** The kernel is the (2R+1)² window of cells. The Airy tails fall only as\n * r⁻³, so a finite window always misses some energy: it is reported per wavelength, and the window is then\n * renormalized to unit sum because the sampled-profile contract requires unit-energy kernels. The missing\n * tail energy is thereby put back inside the window (an approximation that slightly raises low-frequency\n * contrast compared with the untruncated pattern).\n *\n * **Approximations (labelled):** scalar (no polarization), aberration-free, uniform pupil amplitude, exactly in\n * focus (no defocus), thin lens with unity pupil magnification, the on-axis PSF used across the declared field\n * (isoplanatic), PSF energy binned into the sample cells, finite window renormalized. Not a measured lens.\n * @see docs/PSF_FOUNDATION.md, \"Diffraction-limited sampled profile (2.1)\".\n */\n\nimport { approximationResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireAllowlistedRecord } from \"../core/record-validation.js\";\nimport type { EvidenceProvenance } from \"../core/evidence-provenance.js\";\nimport type { FocusPlane } from \"./focus-state.js\";\nimport { calculateThinLensImageDistance } from \"./thin-lens.js\";\nimport { parseLensSampledPsfProfile, type LensSampledPsfProfile } from \"./lens-psf-profile.js\";\n\nexport const DIFFRACTION_LIMITED_PSF_PROFILE_MODEL = Object.freeze({\n modelId: \"photivra-diffraction-limited-circular-pupil-psf\" as const, modelVersion: \"1.0.0\" as const });\n/** Input limits: at most 64 wavelengths, kernel radius 0–32 samples (the irradiance-convolution limit). */\nexport const DIFFRACTION_LIMITED_PSF_PROFILE_LIMITS = Object.freeze({ maximumWavelengths: 64, maximumKernelRadiusSamples: 32 });\n/**\n * Internal: β = p·f_c (cell side over the cut-off period) from which `calculateAiryCellEnergies` integrates the cells in\n * real space (2.5). Above every β of a `simulateCapture` pitch up to 100 µm, whose captures keep the frequency-domain values.\n */\nexport const AIRY_REAL_SPACE_MINIMUM_BETA = 32;\n/** Radius of the first dark ring of the Airy pattern in units of λ·N_w: j₁,₁/π, j₁,₁ = 3.8317059702 (first zero of J₁). */\nconst AIRY_FIRST_ZERO_PER_LAMBDA_N = 3.8317059702075125 / Math.PI;\n\nexport interface CreateDiffractionLimitedPsfProfileInput {\n /** Only `circular` in 2.1.0 (polygon pupils: `calculateIdealPolygonDiffractionPsf` gives point densities). */\n aperture: \"circular\";\n focalLengthMm: number;\n apertureFNumber: number;\n focus: FocusPlane;\n /** Strictly increasing wavelengths, nm, in the medium of propagation (no air/vacuum conversion is applied). 1–64. */\n wavelengthsNm: readonly number[];\n /** Square sample pitch of every kernel, µm. */\n samplePitchMicrometers: number;\n /** Kernel half-width in samples; each kernel is (2R + 1)². 0–32. */\n kernelRadiusSamples: number;\n /** Half-extent of the image field over which the on-axis PSF is declared (profile field axes ±x, ±y), mm. */\n fieldHalfExtentMm: { x: number; y: number };\n profileId: string;\n}\n\nexport interface DiffractionLimitedPsfWavelength {\n wavelengthNm: number;\n /** f_c = 1/(λ·N_w), cycles per µm. */\n cutoffFrequencyCyclesPerMicrometer: number;\n /** 1.21967·λ·N_w, µm. */\n firstZeroRadiusMicrometers: number;\n /** Σ of the cell energies inside the window before renormalization (of a total of 1). */\n capturedEnergyFraction: number;\n /** 1 − capturedEnergyFraction: the Airy tail energy outside the window, put back by renormalization. */\n truncatedEnergyFraction: number;\n /** Fraction of the renormalized kernel in the centre sample. */\n centreSampleFraction: number;\n}\n\nexport interface DiffractionLimitedPsfProfile {\n profile: LensSampledPsfProfile;\n model: typeof DIFFRACTION_LIMITED_PSF_PROFILE_MODEL;\n pupilDiameterMm: number;\n pupilToImageDistanceMm: number;\n workingFNumber: number;\n kernelRadiusSamples: number;\n samplePitchMicrometers: number;\n wavelengths: readonly DiffractionLimitedPsfWavelength[];\n /** Largest truncated energy over the wavelengths. */\n maximumTruncatedEnergyFraction: number;\n /**\n * How the cells were integrated. 2.5: wavelengths with β = p·f_c ≥ `AIRY_REAL_SPACE_MINIMUM_BETA` (192 in 2.5–2.8.1, then 32) use the real-space\n * encircled-energy method; `realSpaceWavelengthsNm` lists them, and `method` is `\"frequency-domain-and-real-space\"` when both ran.\n * `maximumRadialNodes` counts frequency-domain radial nodes (0 when only the real-space method ran); `maximumAngularNodes` the\n * angular nodes of either method (for the real-space method, all θ nodes of one wavelength).\n */\n quadrature: { method: \"polar-frequency-domain-trapezoid-gauss-legendre\" | \"real-space-encircled-energy-gauss-legendre\" | \"frequency-domain-and-real-space\";\n maximumRadialNodes: number; maximumAngularNodes: number; realSpaceWavelengthsNm?: readonly number[] };\n}\n\nconst EVIDENCE: readonly EvidenceProvenance[] = Object.freeze([Object.freeze({ sourceOrigin: \"photivra\" as const,\n sourceReference: \"photivra:diffraction-limited-psf-profile\", reuseStatus: \"photivra-owned\" as const })]);\nconst LIMITATIONS = Object.freeze([\n \"Scalar Fraunhofer diffraction of an ideal, uniformly lit circular pupil (Airy pattern); no aberration, apodization, polarization or stray light.\",\n \"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.\",\n \"The on-axis PSF is declared unchanged across the field (isoplanatic); no field-dependent aberration or pupil clipping.\",\n \"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.\",\n \"Wavelengths are used as given, in the declared basis, without air/vacuum conversion.\"\n]);\n\nfunction positive(value: unknown, name: string): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) throw new InvalidConfigurationError(name + \" must be a positive finite number.\");\n return value;\n}\n\n/** Gauss–Legendre nodes and weights on [0, 1] (Newton iteration on Pₙ; DLMF §3.5(v)). Cached per n. */\nconst GAUSS_LEGENDRE = new Map<number, { nodes: Float64Array; weights: Float64Array }>();\nfunction gaussLegendre(n: number): { nodes: Float64Array; weights: Float64Array } {\n const cached = GAUSS_LEGENDRE.get(n);\n if (cached) return cached;\n const nodes = new Float64Array(n), weights = new Float64Array(n);\n for (let k = 0; k < Math.ceil(n / 2); k++) {\n let x = Math.cos(Math.PI * (k + 0.75) / (n + 0.5));\n for (let iteration = 0; iteration < 100; iteration++) {\n let p0 = 1, p1 = x;\n for (let m = 2; m <= n; m++) { const p2 = ((2 * m - 1) * x * p1 - (m - 1) * p0) / m; p0 = p1; p1 = p2; }\n const step = p1 / (n * (x * p1 - p0) / (x * x - 1));\n x -= step;\n if (Math.abs(step) < 1e-16) break;\n }\n let p0 = 1, p1 = x;\n for (let m = 2; m <= n; m++) { const p2 = ((2 * m - 1) * x * p1 - (m - 1) * p0) / m; p0 = p1; p1 = p2; }\n const derivative = n * (x * p1 - p0) / (x * x - 1);\n const w = 1 / ((1 - x * x) * derivative * derivative);\n // Map [-1, 1] to [0, 1]: t = (1 ± x)/2, weight w (2/(1-x²)P'² halved).\n nodes[k] = (1 - x) / 2; weights[k] = w;\n nodes[n - 1 - k] = (1 + x) / 2; weights[n - 1 - k] = w;\n }\n const result = { nodes, weights };\n if (GAUSS_LEGENDRE.size < 64) GAUSS_LEGENDRE.set(n, result);\n return result;\n}\nfunction sinc(x: number): number {\n if (x === 0) return 1;\n const a = Math.PI * x;\n return Math.sin(a) / a;\n}\n\n/**\n * 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\n * period): in the frequency domain below `AIRY_REAL_SPACE_MINIMUM_BETA`, in real space from it (2.5). `scale`\n * multiplies the node or panel counts (1 in production; the tests use 2 to check convergence).\n */\nexport function calculateAiryCellEnergies(beta: number, radius: number, scale = 1): { cells: Float64Array; radialNodes: number; angularNodes: number; realSpace: boolean } {\n // 2.6: a pure function of (β, R, scale), so results are memoized (most recently used first) and handed out as copies.\n // Tiles of one frame, and captures that change only the exposure or the scene, rebuild the same kernels.\n const key = beta + \"|\" + radius + \"|\" + scale, cached = AIRY_CELL_CACHE.get(key);\n if (cached) {\n AIRY_CELL_CACHE.delete(key); AIRY_CELL_CACHE.set(key, cached);\n return { ...cached, cells: cached.cells.slice() };\n }\n const result = beta >= AIRY_REAL_SPACE_MINIMUM_BETA ? { ...calculateAiryCellEnergiesInRealSpace(beta, radius, scale), radialNodes: 0, realSpace: true } :\n { ...calculateAiryCellEnergiesInFrequencyDomain(beta, radius, scale), realSpace: false };\n AIRY_CELL_CACHE.set(key, { ...result, cells: result.cells.slice() });\n if (AIRY_CELL_CACHE.size > AIRY_CELL_CACHE_ENTRIES) AIRY_CELL_CACHE.delete(AIRY_CELL_CACHE.keys().next().value!);\n return result;\n}\n/** Memoized cell energies (2.6): 256 entries of (R + 1)² values, at most 256 × 33² × 8 bytes ≈ 2.2 MB. */\nconst AIRY_CELL_CACHE_ENTRIES = 256;\nconst AIRY_CELL_CACHE = new Map<string, { cells: Float64Array; radialNodes: number; angularNodes: number; realSpace: boolean }>();\n\n/** Hankel asymptotic coefficients a_k(ν) of DLMF 10.17.1 for ν = 0 and 1, k = 0..15. */\nconst HANKEL = ((): { a0: Float64Array; a1: Float64Array } => {\n const a0 = new Float64Array(16), a1 = new Float64Array(16);\n a0[0] = 1; a1[0] = 1;\n for (let k = 1; k < 16; k++) {\n const odd = (2 * k - 1) * (2 * k - 1);\n a0[k] = a0[k - 1]! * (0 - odd) / (8 * k);\n a1[k] = a1[k - 1]! * (4 - odd) / (8 * k);\n }\n return { a0, a1 };\n})();\n/** Smallest argument of `besselSquareSum`: there the 16-term expansion's remainder is below 1e-17. */\nconst HANKEL_MINIMUM_ARGUMENT = 300;\n\n/**\n * J₀(x)² + J₁(x)² for x > 0. From x ≥ 300 by the Hankel expansion J_ν(x) = √(2/(πx))·(P_ν cos ω_ν − Q_ν sin ω_ν), ω_ν = x − νπ/2 − π/4,\n * P_ν = Σ(−1)^k a_2k(ν)/x^2k, Q_ν = Σ(−1)^k a_2k+1(ν)/x^2k+1 (DLMF 10.17.3), eight terms each. With ω₁ = ω₀ − π/2,\n * J₁ = √(2/(πx))·(P₁ sin ω₀ + Q₁ cos ω₀). Below 300 by Miller's backward recurrence J_{n−1} = (2n/x)·J_n − J_{n+1} (DLMF 10.6.1;\n * the algorithm, DLMF §3.6(iii)), started at an order above x where J_n is negligible, normalized by J₀ + 2·Σ J_2k = 1\n * (DLMF 10.12.4). Internal.\n */\nexport function besselSquareSum(x: number): number {\n if (!(x > 0) || !Number.isFinite(x)) throw new InvalidConfigurationError(\"J0 and J1 need a positive finite argument.\");\n if (x < HANKEL_MINIMUM_ARGUMENT) return besselSquareSumByRecurrence(x);\n const { a0, a1 } = HANKEL, inverse = 1 / x;\n let p0 = 0, q0 = 0, p1 = 0, q1 = 0, power = 1;\n for (let k = 0; k < 16; k++) {\n const sign = (k >> 1) % 2 === 0 ? 1 : -1;\n if (k % 2 === 0) { p0 += sign * a0[k]! * power; p1 += sign * a1[k]! * power; } else { q0 += sign * a0[k]! * power; q1 += sign * a1[k]! * power; }\n power *= inverse;\n }\n const omega = x - Math.PI / 4, c = Math.cos(omega), s = Math.sin(omega);\n const j0 = p0 * c - q0 * s, j1 = p1 * s + q1 * c;\n return 2 / (Math.PI * x) * (j0 * j0 + j1 * j1);\n}\n/**\n * Miller's backward recurrence for 0 < x < 300 (see `besselSquareSum`). The start order x + 10·∛x + 40 (even) lies far enough in the\n * region where J_n(x) falls faster than exponentially that the start values' error is below double precision at J₀ and J₁; the\n * values are rescaled when they grow large, and normalized before squaring.\n */\nfunction besselSquareSumByRecurrence(x: number): number {\n const start = 2 * Math.ceil((x + 10 * Math.cbrt(x) + 40) / 2);\n let next = 0, current = 1e-100, sum = 0, j1 = 0;\n for (let n = start; n >= 1; n--) {\n const previous = (2 * n / x) * current - next;\n next = current; current = previous;\n if (n - 1 === 1) j1 = current;\n if (n - 1 > 0 && (n - 1) % 2 === 0) sum += 2 * current;\n if (Math.abs(current) > 1e100) { current *= 1e-100; next *= 1e-100; sum *= 1e-100; j1 *= 1e-100; }\n }\n sum += current;\n const j0 = current / sum, j1n = j1 / sum;\n return j0 * j0 + j1n * j1n;\n}\n\n/**\n * Real-space cell energies (2.5): see the module comment. G(Z, φ) = ∫₀^φ [J₀² + J₁²](π·β·Z/cos θ) dθ for cell boundaries at\n * half-integer distances Z (in cells), accumulated along θ for each Z with every needed φ = atan(W/Z) as a panel boundary.\n * The rectangle [0, X] × [0, Y] holds 1/4 − (G(X, atan(Y/X)) + G(Y, atan(X/Y)))/(2π) of the energy. Internal.\n */\nexport function calculateAiryCellEnergiesInRealSpace(beta: number, radius: number, scale = 1): { cells: Float64Array; angularNodes: number } {\n const size = radius + 1, table = new Float64Array(size * size), { nodes, weights } = gaussLegendre(16);\n let angularNodes = 0;\n for (let z = 0; z < size; z++) {\n const Z = z + 0.5, k = Math.PI * beta * Z;\n let sum = 0, t0 = 1, theta0 = 0;\n for (let w = 0; w < size; w++) {\n // Panels equal in t = 1/cos θ, so the phase 2x = 2kt changes by at most 2 radians on each.\n const t1 = Math.hypot(Z, w + 0.5) / Z, theta1 = Math.atan2(w + 0.5, Z), panels = Math.max(1, Math.ceil(scale * k * (t1 - t0)));\n let a = theta0;\n for (let n = 1; n <= panels; n++) {\n const b = n === panels ? theta1 : Math.acos(1 / (t0 + (t1 - t0) * n / panels)), h = b - a;\n let panel = 0;\n for (let g = 0; g < 16; g++) panel += weights[g]! * besselSquareSum(k / Math.cos(a + h * nodes[g]!));\n sum += panel * h;\n a = b;\n }\n angularNodes += 16 * panels;\n table[z * size + w] = sum;\n t0 = t1; theta0 = theta1;\n }\n }\n // Boundaries of cell i along one axis as (half-integer index, weight): the centre cell is twice [0, 1/2].\n const bounds = (i: number): [number, number][] => i === 0 ? [[0, 2]] : [[i, 1], [i - 1, -1]];\n const cells = new Float64Array(size * size);\n for (let j = 0; j < size; j++) for (let i = 0; i < size; i++) {\n let constant = 0, leak = 0;\n for (const [a, wa] of bounds(i)) for (const [b, wb] of bounds(j)) {\n constant += wa * wb;\n leak += wa * wb * (table[a * size + b]! + table[b * size + a]!);\n }\n cells[j * size + i] = constant / 4 - leak / (2 * Math.PI);\n }\n return { cells, angularNodes };\n}\n\n/** Frequency-domain cell energies (2.1; see the module comment). Internal. */\nexport function calculateAiryCellEnergiesInFrequencyDomain(beta: number, radius: number, scale = 1): { cells: Float64Array; radialNodes: number; angularNodes: number } {\n // Bandwidth of the angular and radial integrands: c = π·β·(2R + 1)·√2 (the sinc factors and the highest cosine).\n const c = Math.PI * beta * (2 * radius + 1) * Math.SQRT2, margin = 10 * Math.cbrt(c) + 24;\n const quarter = Math.ceil(scale * (c + margin) / 4), radialNodes = Math.ceil(scale * (c + margin));\n const { nodes, weights } = gaussLegendre(radialNodes), size = radius + 1, cells = new Float64Array(size * size);\n const ca = new Float64Array(size), cb = new Float64Array(size), angularStep = (Math.PI / 2) / quarter;\n // cos θ and sin θ of every angular node, computed once with the same expressions as inside the loop (same values).\n const cosines = new Float64Array(quarter + 1), sines = new Float64Array(quarter + 1);\n for (let k = 0; k <= quarter; k++) { const theta = k * angularStep; cosines[k] = Math.cos(theta); sines[k] = Math.sin(theta); }\n for (let r = 0; r < radialNodes; r++) {\n const t = nodes[r]!, rho = 1 - t * t;\n // H(1 − t²) without cancellation: acos(1 − t²) = 2·asin(t/√2), ρ·√(1 − ρ²) = ρ·t·√(2 − t²).\n const otf = (2 / Math.PI) * (2 * Math.asin(t / Math.SQRT2) - rho * t * Math.sqrt(2 - t * t));\n // ∫₀¹ g(ρ) dρ = ∫₀¹ g(1 − t²)·2t dt; the 4 is the four symmetric quadrants of the angular trapezoid.\n const radialWeight = weights[r]! * 2 * t * rho * otf * 4 * angularStep;\n for (let k = 0; k <= quarter; k++) {\n const x = beta * rho * cosines[k]!, y = beta * rho * sines[k]!;\n const w = radialWeight * (k === 0 || k === quarter ? 0.5 : 1) * sinc(x) * sinc(y);\n // cos(2π·i·x) and cos(2π·j·y) by the Chebyshev recurrence.\n const cx = Math.cos(2 * Math.PI * x), cy = Math.cos(2 * Math.PI * y);\n ca[0] = 1; cb[0] = 1;\n if (size > 1) { ca[1] = cx; cb[1] = cy; }\n for (let i = 2; i < size; i++) { ca[i] = 2 * cx * ca[i - 1]! - ca[i - 2]!; cb[i] = 2 * cy * cb[i - 1]! - cb[i - 2]!; }\n for (let j = 0; j < size; j++) {\n const wj = w * cb[j]!;\n for (let i = 0; i < size; i++) { const o = j * size + i; cells[o] = cells[o]! + wj * ca[i]!; }\n }\n }\n }\n const area = beta * beta;\n for (let i = 0; i < cells.length; i++) cells[i] = cells[i]! * area;\n return { cells, radialNodes, angularNodes: 4 * quarter };\n}\n\n/**\n * Creates a sampled lens PSF profile for an ideal diffraction-limited lens with a circular pupil: one\n * unit-sum Airy kernel per wavelength on one shared (2R+1)² grid, with the truncated energy reported per\n * wavelength. The profile declares the given focal length, f-number and focus exactly, and the field axes\n * ±`fieldHalfExtentMm` with the same kernel at every field node.\n * @param input - See `CreateDiffractionLimitedPsfProfileInput`.\n * @returns The profile and its diffraction record. An approximation; not a measured lens.\n * @see docs/PSF_FOUNDATION.md, \"Diffraction-limited sampled profile (2.1)\".\n */\nexport function createDiffractionLimitedPsfProfile(input: CreateDiffractionLimitedPsfProfileInput): CalculationResult<DiffractionLimitedPsfProfile> {\n const r = requireAllowlistedRecord(input, [\"aperture\", \"focalLengthMm\", \"apertureFNumber\", \"focus\", \"wavelengthsNm\", \"samplePitchMicrometers\",\n \"kernelRadiusSamples\", \"fieldHalfExtentMm\", \"profileId\"], \"Invalid diffraction-limited PSF profile input.\");\n if (r.aperture !== \"circular\") throw new InvalidConfigurationError(\"aperture must be \\\"circular\\\".\");\n const focalLengthMm = positive(r.focalLengthMm, \"focalLengthMm\"), fNumber = positive(r.apertureFNumber, \"apertureFNumber\");\n const pitch = positive(r.samplePitchMicrometers, \"samplePitchMicrometers\");\n const L = DIFFRACTION_LIMITED_PSF_PROFILE_LIMITS;\n const radius = r.kernelRadiusSamples;\n if (typeof radius !== \"number\" || !Number.isSafeInteger(radius) || radius < 0 || radius > L.maximumKernelRadiusSamples) {\n throw new InvalidConfigurationError(\"kernelRadiusSamples must be an integer from 0 to \" + L.maximumKernelRadiusSamples + \".\");\n }\n const focus = requireAllowlistedRecord(r.focus, [\"kind\", \"distanceM\"], \"Invalid focus.\");\n let focusDiopters: number, distanceMm: number;\n if (focus.kind === \"infinity\") {\n if (focus.distanceM !== undefined) throw new InvalidConfigurationError(\"An infinity focus has no distanceM.\");\n focusDiopters = 0; distanceMm = focalLengthMm;\n } else if (focus.kind === \"finite\") {\n const distanceM = positive(focus.distanceM, \"focus.distanceM\");\n focusDiopters = 1 / distanceM;\n distanceMm = calculateThinLensImageDistance({ focalLengthMm, objectDistanceM: distanceM }).value.imageDistanceMm;\n } else throw new InvalidConfigurationError(\"focus.kind must be finite or infinity.\");\n const field = requireAllowlistedRecord(r.fieldHalfExtentMm, [\"x\", \"y\"], \"Invalid fieldHalfExtentMm.\");\n const fieldX = positive(field.x, \"fieldHalfExtentMm.x\"), fieldY = positive(field.y, \"fieldHalfExtentMm.y\");\n const list = r.wavelengthsNm;\n if (!Array.isArray(list) || list.length < 1 || list.length > L.maximumWavelengths) throw new InvalidConfigurationError(\"wavelengthsNm must list 1 to 64 wavelengths.\");\n const wavelengths = (list as unknown[]).map((value, index) => positive(value, \"wavelengthsNm[\" + index + \"]\"));\n for (let i = 1; i < wavelengths.length; i++) if (!(wavelengths[i]! > wavelengths[i - 1]!)) throw new InvalidConfigurationError(\"wavelengthsNm must be strictly increasing.\");\n if (typeof r.profileId !== \"string\" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(r.profileId)) throw new InvalidConfigurationError(\"profileId must be a public opaque ID.\");\n\n const pupilDiameterMm = focalLengthMm / fNumber, workingFNumber = distanceMm / pupilDiameterMm, size = 2 * radius + 1;\n let maximumRadialNodes = 0, maximumAngularNodes = 0, maximumTruncated = 0;\n const records: DiffractionLimitedPsfWavelength[] = [], kernels: number[][] = [], realSpaceWavelengthsNm: number[] = [];\n for (const nm of wavelengths) {\n const lambdaN = nm / 1000 * workingFNumber, cutoff = 1 / lambdaN;\n const airy = calculateAiryCellEnergies(pitch * cutoff, radius);\n if (airy.realSpace) realSpaceWavelengthsNm.push(nm);\n maximumRadialNodes = Math.max(maximumRadialNodes, airy.radialNodes); maximumAngularNodes = Math.max(maximumAngularNodes, airy.angularNodes);\n const values: number[] = new Array(size * size);\n let captured = 0;\n for (let ky = 0; ky < size; ky++) for (let kx = 0; kx < size; kx++) {\n const value = airy.cells[Math.abs(ky - radius) * (radius + 1) + Math.abs(kx - radius)]!;\n // Every cell energy of a non-negative PSF is positive; a negative value would be a quadrature failure.\n if (!(value > -1e-13)) throw new InvalidConfigurationError(\"Diffraction cell integration failed to converge.\");\n values[ky * size + kx] = Math.max(0, value);\n captured += values[ky * size + kx]!;\n }\n if (!(captured > 0 && captured <= 1 + 1e-9)) throw new InvalidConfigurationError(\"Diffraction cell integration failed to converge.\");\n const truncated = Math.max(0, 1 - captured);\n maximumTruncated = Math.max(maximumTruncated, truncated);\n const kernel = values.map((v) => v / captured);\n kernels.push(kernel);\n records.push({ wavelengthNm: nm, cutoffFrequencyCyclesPerMicrometer: cutoff, firstZeroRadiusMicrometers: AIRY_FIRST_ZERO_PER_LAMBDA_N * lambdaN,\n capturedEnergyFraction: captured, truncatedEnergyFraction: truncated, centreSampleFraction: kernel[radius * size + radius]! });\n }\n const uncertainty = { kind: \"not-quantified\" as const, limitation: \"Ideal diffraction-limited model; no measured lens or quadrature error bound.\" };\n const nodes = [-fieldX, fieldX].flatMap((fx) => [-fieldY, fieldY].flatMap((fy) => wavelengths.map((nm, index) => ({\n nodeId: \"airy-\" + (fx < 0 ? \"xm\" : \"xp\") + \"-\" + (fy < 0 ? \"ym\" : \"yp\") + \"-\" + index,\n coordinate: { focalLengthMm, focusDiopters, apertureFNumber: fNumber, fieldXmm: fx, fieldYmm: fy, wavelengthNm: nm, signedDefocusImagePlaneMicrometers: 0 },\n kernel: { widthSamples: size, heightSamples: size, samplePitchMicrometersX: pitch, samplePitchMicrometersY: pitch, centerSampleX: radius, centerSampleY: radius,\n normalizedIntensity: kernels[index]! },\n bestFocusImagePlaneOffsetMicrometers: 0, relativePupilThroughputFactor: 1, evidence: EVIDENCE, uncertainty }))));\n const profile = parseLensSampledPsfProfile({ schemaVersion: \"0.1.0\", profileId: r.profileId, profileVersion: DIFFRACTION_LIMITED_PSF_PROFILE_MODEL.modelVersion,\n scientificStatus: \"approximation\", opticalDomain: \"lens-primary-optical-path-only\", coordinateSystem: \"image-plane-metric\", fieldAxes: \"+X right, +Y up\",\n kernelEnergyNormalization: \"unit-energy-shape\", interpolation: \"bounded-regular-grid-multilinear\", throughputOwnership: \"separate-relative-pupil-throughput-factor\",\n responseIncludes: { diffraction: true, aberration: false, defocus: false, pupilClippingShape: false },\n sensorOpticalStackIncluded: false, sensorSamplingIncluded: false, reconstructionIncluded: false, strayLightIncluded: false,\n axes: { focalLengthMm: [focalLengthMm], focusDiopters: [focusDiopters], apertureFNumber: [fNumber], fieldXmm: [-fieldX, fieldX], fieldYmm: [-fieldY, fieldY],\n wavelengthNm: wavelengths, signedDefocusImagePlaneMicrometers: [0] },\n nodes, evidence: EVIDENCE, limitations: [...LIMITATIONS] });\n return approximationResult({ profile, model: DIFFRACTION_LIMITED_PSF_PROFILE_MODEL, pupilDiameterMm, pupilToImageDistanceMm: distanceMm, workingFNumber,\n kernelRadiusSamples: radius, samplePitchMicrometers: pitch, wavelengths: records, maximumTruncatedEnergyFraction: maximumTruncated,\n quadrature: realSpaceWavelengthsNm.length === 0 ? { method: \"polar-frequency-domain-trapezoid-gauss-legendre\" as const, maximumRadialNodes, maximumAngularNodes } :\n { method: realSpaceWavelengthsNm.length === wavelengths.length ? \"real-space-encircled-energy-gauss-legendre\" as const : \"frequency-domain-and-real-space\" as const,\n maximumRadialNodes, maximumAngularNodes, realSpaceWavelengthsNm } },\n DIFFRACTION_LIMITED_PSF_PROFILE_MODEL.modelId, DIFFRACTION_LIMITED_PSF_PROFILE_MODEL.modelVersion, [...LIMITATIONS]);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"diffraction-psf-profile.js","sourceRoot":"","sources":["../../src/optics/diffraction-psf-profile.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Builds a `LensSampledPsfProfile` for an ideal, aberration-free, in-focus lens with a uniformly lit\n * circular pupil: the Airy pattern of scalar Fraunhofer diffraction, one unit-sum kernel per declared\n * wavelength on ONE shared sample grid (2.1.0).\n *\n * **Model.** The pupil diameter is D = f/N (entrance pupil = exit pupil, unity pupil magnification) and\n * the pupil-to-image distance z is the thin-lens image distance for the focus (f at infinity), so the\n * image-side (working) f-number is N_w = z/D. The incoherent optical transfer function (OTF) of a\n * uniform circular pupil is the normalized autocorrelation of the pupil,\n * H(ρ) = (2/π)·(acos ρ − ρ·√(1 − ρ²)), ρ = |f|/f_c ≤ 1, f_c = 1/(λ·N_w),\n * and the intensity PSF is its inverse Fourier transform (the Airy pattern, first zero at 1.21967·λ·N_w)\n * (MIT OpenCourseWare 2.71 Optics, Spring 2009, lectures 21–22, free: the intensity PSF as the transform of\n * the pupil autocorrelation and the circular-pupil MTF; also see: Goodman, Introduction to Fourier Optics,\n * 4th ed., 2017, §7.3).\n *\n * **Cell integration (exact, no Bessel functions).** Kernel sample (i, j) is the PSF energy inside the\n * square cell of side p centred on (i·p, j·p). The cell integral is the PSF convolved with the cell's\n * indicator, evaluated at the cell centre, so in the frequency domain\n * 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,\n * with sinc(x) = sin(πx)/(πx) (the sine terms vanish because H is even). It is evaluated in polar\n * coordinates: a trapezoid rule in angle (exponentially convergent for this smooth periodic integrand) and\n * Gauss–Legendre in t with ρ = 1 − t², which removes the (1 − ρ)^{3/2} edge behaviour of H. The node counts\n * follow from the integrand's bandwidth with a fixed margin; the tests check convergence by doubling them and\n * check the values against an independent real-space integration of `calculateIdealPolygonDiffractionPsf` in\n * its many-blade (circular) limit. The sum of all cells is exactly 1 (Parseval), so the energy captured by\n * the finite kernel is Σ K over its window and the truncated energy is 1 − Σ K.\n *\n * **Cells much larger than the pattern (2.5; threshold lowered to β = 32 after 2.8.1).** The frequency-domain node counts grow with β = p·f_c (the\n * cell side over the cut-off period), so the work grows as β². From β ≥ `AIRY_REAL_SPACE_MINIMUM_BETA` (32) the cells are\n * integrated in real space instead, with the same model and no frequency integral: the Airy encircled energy is\n * EE(r) = 1 − J₀(x)² − J₁(x)², x = π·r·f_c (it follows from J₀′ = −J₁ and J₁′ = J₀ − J₁/x, DLMF §10.6(i), free), so\n * the energy of the rectangle [0, X] × [0, Y] is (1/2π)∫ EE(r_edge(θ)) dθ over its quadrant, a one-dimensional\n * integral in θ. Every cell is a signed sum of such rectangles. J₀² + J₁² comes from the Hankel asymptotic expansion\n * (DLMF §10.17(i), eq. 10.17.3, free) from x = 300, with eight terms in each of P and Q (remainder under 1e-17,\n * DLMF §10.17(iii)), and below it from Miller's backward recurrence normalized by J₀ + 2ΣJ₂ₖ = 1 (DLMF §3.6(iii),\n * 10.12.4, free). The θ integral uses 16-point Gauss–Legendre panels on which the phase 2x changes by at most\n * 2 radians, so the work grows only as β. The tests check the two methods against each other from β = 32 to 400, the\n * real-space cells against the asymptotic leakage 8√2/(π³·β) of the centre cell, and convergence under doubled panel\n * counts. The threshold was 192 in 2.5; it moved to 32 because from there the real-space cells agree with the frequency-domain cells\n * within about 1e-12 and cost a few to a few hundred times less (a 750 µm whole-frame cell at f/8 took 3.4 s for 20\n * wavelengths). Every β a native pitch up to 10 µm reaches (at most 10/(0.38·1.4) ≈ 19) stays in the frequency domain,\n * so captures at sensor pitch are unchanged; larger cells (binned and whole-frame views) change in the last bits only.\n *\n * **Reuse (2.6).** The cells depend only on (β, R) (and the test-only node scale), so `calculateAiryCellEnergies` keeps the\n * 256 most recently used results and returns copies: tiles of one frame rendered in the same worker, and captures that\n * change only the exposure, ISO, scene or output, reuse the kernels instead of integrating them again. The frequency-domain\n * loop also takes cos θ and sin θ from a per-call table computed with the same expressions, so the values are unchanged.\n *\n * **Truncation and normalization.** The kernel is the (2R+1)² window of cells. The Airy tails fall only as\n * r⁻³, so a finite window always misses some energy: it is reported per wavelength, and the window is then\n * renormalized to unit sum because the sampled-profile contract requires unit-energy kernels. The missing\n * tail energy is thereby put back inside the window (an approximation that slightly raises low-frequency\n * contrast compared with the untruncated pattern).\n *\n * **Approximations (labelled):** scalar (no polarization), aberration-free, uniform pupil amplitude, exactly in\n * focus (no defocus), thin lens with unity pupil magnification, the on-axis PSF used across the declared field\n * (isoplanatic), PSF energy binned into the sample cells, finite window renormalized. Not a measured lens.\n * @see docs/PSF_FOUNDATION.md, \"Diffraction-limited sampled profile (2.1)\".\n */\n\nimport { approximationResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireAllowlistedRecord } from \"../core/record-validation.js\";\nimport type { EvidenceProvenance } from \"../core/evidence-provenance.js\";\nimport type { FocusPlane } from \"./focus-state.js\";\nimport { calculateThinLensImageDistance } from \"./thin-lens.js\";\nimport { parseLensSampledPsfProfile, type LensSampledPsfProfile } from \"./lens-psf-profile.js\";\n\nexport const DIFFRACTION_LIMITED_PSF_PROFILE_MODEL = /* @__PURE__ */ Object.freeze({\n modelId: \"photivra-diffraction-limited-circular-pupil-psf\" as const, modelVersion: \"1.0.0\" as const });\n/** Input limits: at most 64 wavelengths, kernel radius 0–32 samples (the irradiance-convolution limit). */\nexport const DIFFRACTION_LIMITED_PSF_PROFILE_LIMITS = /* @__PURE__ */ Object.freeze({ maximumWavelengths: 64, maximumKernelRadiusSamples: 32 });\n/**\n * Internal: β = p·f_c (cell side over the cut-off period) from which `calculateAiryCellEnergies` integrates the cells in\n * real space (2.5). Above every β of a `simulateCapture` pitch up to 100 µm, whose captures keep the frequency-domain values.\n */\nexport const AIRY_REAL_SPACE_MINIMUM_BETA = 32;\n/** Radius of the first dark ring of the Airy pattern in units of λ·N_w: j₁,₁/π, j₁,₁ = 3.8317059702 (first zero of J₁). */\nconst AIRY_FIRST_ZERO_PER_LAMBDA_N = 3.8317059702075125 / Math.PI;\n\nexport interface CreateDiffractionLimitedPsfProfileInput {\n /** Only `circular` in 2.1.0 (polygon pupils: `calculateIdealPolygonDiffractionPsf` gives point densities). */\n aperture: \"circular\";\n focalLengthMm: number;\n apertureFNumber: number;\n focus: FocusPlane;\n /** Strictly increasing wavelengths, nm, in the medium of propagation (no air/vacuum conversion is applied). 1–64. */\n wavelengthsNm: readonly number[];\n /** Square sample pitch of every kernel, µm. */\n samplePitchMicrometers: number;\n /** Kernel half-width in samples; each kernel is (2R + 1)². 0–32. */\n kernelRadiusSamples: number;\n /** Half-extent of the image field over which the on-axis PSF is declared (profile field axes ±x, ±y), mm. */\n fieldHalfExtentMm: { x: number; y: number };\n profileId: string;\n}\n\nexport interface DiffractionLimitedPsfWavelength {\n wavelengthNm: number;\n /** f_c = 1/(λ·N_w), cycles per µm. */\n cutoffFrequencyCyclesPerMicrometer: number;\n /** 1.21967·λ·N_w, µm. */\n firstZeroRadiusMicrometers: number;\n /** Σ of the cell energies inside the window before renormalization (of a total of 1). */\n capturedEnergyFraction: number;\n /** 1 − capturedEnergyFraction: the Airy tail energy outside the window, put back by renormalization. */\n truncatedEnergyFraction: number;\n /** Fraction of the renormalized kernel in the centre sample. */\n centreSampleFraction: number;\n}\n\nexport interface DiffractionLimitedPsfProfile {\n profile: LensSampledPsfProfile;\n model: typeof DIFFRACTION_LIMITED_PSF_PROFILE_MODEL;\n pupilDiameterMm: number;\n pupilToImageDistanceMm: number;\n workingFNumber: number;\n kernelRadiusSamples: number;\n samplePitchMicrometers: number;\n wavelengths: readonly DiffractionLimitedPsfWavelength[];\n /** Largest truncated energy over the wavelengths. */\n maximumTruncatedEnergyFraction: number;\n /**\n * How the cells were integrated. 2.5: wavelengths with β = p·f_c ≥ `AIRY_REAL_SPACE_MINIMUM_BETA` (192 in 2.5–2.8.1, then 32) use the real-space\n * encircled-energy method; `realSpaceWavelengthsNm` lists them, and `method` is `\"frequency-domain-and-real-space\"` when both ran.\n * `maximumRadialNodes` counts frequency-domain radial nodes (0 when only the real-space method ran); `maximumAngularNodes` the\n * angular nodes of either method (for the real-space method, all θ nodes of one wavelength).\n */\n quadrature: { method: \"polar-frequency-domain-trapezoid-gauss-legendre\" | \"real-space-encircled-energy-gauss-legendre\" | \"frequency-domain-and-real-space\";\n maximumRadialNodes: number; maximumAngularNodes: number; realSpaceWavelengthsNm?: readonly number[] };\n}\n\nconst EVIDENCE: readonly EvidenceProvenance[] = /* @__PURE__ */ Object.freeze([/* @__PURE__ */ Object.freeze({ sourceOrigin: \"photivra\" as const,\n sourceReference: \"photivra:diffraction-limited-psf-profile\", reuseStatus: \"photivra-owned\" as const })]);\nconst LIMITATIONS = /* @__PURE__ */ Object.freeze([\n \"Scalar Fraunhofer diffraction of an ideal, uniformly lit circular pupil (Airy pattern); no aberration, apodization, polarization or stray light.\",\n \"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.\",\n \"The on-axis PSF is declared unchanged across the field (isoplanatic); no field-dependent aberration or pupil clipping.\",\n \"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.\",\n \"Wavelengths are used as given, in the declared basis, without air/vacuum conversion.\"\n]);\n\nfunction positive(value: unknown, name: string): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) throw new InvalidConfigurationError(name + \" must be a positive finite number.\");\n return value;\n}\n\n/** Gauss–Legendre nodes and weights on [0, 1] (Newton iteration on Pₙ; DLMF §3.5(v)). Cached per n. */\nconst GAUSS_LEGENDRE = new Map<number, { nodes: Float64Array; weights: Float64Array }>();\nfunction gaussLegendre(n: number): { nodes: Float64Array; weights: Float64Array } {\n const cached = GAUSS_LEGENDRE.get(n);\n if (cached) return cached;\n const nodes = new Float64Array(n), weights = new Float64Array(n);\n for (let k = 0; k < Math.ceil(n / 2); k++) {\n let x = Math.cos(Math.PI * (k + 0.75) / (n + 0.5));\n for (let iteration = 0; iteration < 100; iteration++) {\n let p0 = 1, p1 = x;\n for (let m = 2; m <= n; m++) { const p2 = ((2 * m - 1) * x * p1 - (m - 1) * p0) / m; p0 = p1; p1 = p2; }\n const step = p1 / (n * (x * p1 - p0) / (x * x - 1));\n x -= step;\n if (Math.abs(step) < 1e-16) break;\n }\n let p0 = 1, p1 = x;\n for (let m = 2; m <= n; m++) { const p2 = ((2 * m - 1) * x * p1 - (m - 1) * p0) / m; p0 = p1; p1 = p2; }\n const derivative = n * (x * p1 - p0) / (x * x - 1);\n const w = 1 / ((1 - x * x) * derivative * derivative);\n // Map [-1, 1] to [0, 1]: t = (1 ± x)/2, weight w (2/(1-x²)P'² halved).\n nodes[k] = (1 - x) / 2; weights[k] = w;\n nodes[n - 1 - k] = (1 + x) / 2; weights[n - 1 - k] = w;\n }\n const result = { nodes, weights };\n if (GAUSS_LEGENDRE.size < 64) GAUSS_LEGENDRE.set(n, result);\n return result;\n}\nfunction sinc(x: number): number {\n if (x === 0) return 1;\n const a = Math.PI * x;\n return Math.sin(a) / a;\n}\n\n/**\n * 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\n * period): in the frequency domain below `AIRY_REAL_SPACE_MINIMUM_BETA`, in real space from it (2.5). `scale`\n * multiplies the node or panel counts (1 in production; the tests use 2 to check convergence).\n */\nexport function calculateAiryCellEnergies(beta: number, radius: number, scale = 1): { cells: Float64Array; radialNodes: number; angularNodes: number; realSpace: boolean } {\n // 2.6: a pure function of (β, R, scale), so results are memoized (most recently used first) and handed out as copies.\n // Tiles of one frame, and captures that change only the exposure or the scene, rebuild the same kernels.\n const key = beta + \"|\" + radius + \"|\" + scale, cached = AIRY_CELL_CACHE.get(key);\n if (cached) {\n AIRY_CELL_CACHE.delete(key); AIRY_CELL_CACHE.set(key, cached);\n return { ...cached, cells: cached.cells.slice() };\n }\n const result = beta >= AIRY_REAL_SPACE_MINIMUM_BETA ? { ...calculateAiryCellEnergiesInRealSpace(beta, radius, scale), radialNodes: 0, realSpace: true } :\n { ...calculateAiryCellEnergiesInFrequencyDomain(beta, radius, scale), realSpace: false };\n AIRY_CELL_CACHE.set(key, { ...result, cells: result.cells.slice() });\n if (AIRY_CELL_CACHE.size > AIRY_CELL_CACHE_ENTRIES) AIRY_CELL_CACHE.delete(AIRY_CELL_CACHE.keys().next().value!);\n return result;\n}\n/** Memoized cell energies (2.6): 256 entries of (R + 1)² values, at most 256 × 33² × 8 bytes ≈ 2.2 MB. */\nconst AIRY_CELL_CACHE_ENTRIES = 256;\nconst AIRY_CELL_CACHE = new Map<string, { cells: Float64Array; radialNodes: number; angularNodes: number; realSpace: boolean }>();\n\n/** Hankel asymptotic coefficients a_k(ν) of DLMF 10.17.1 for ν = 0 and 1, k = 0..15. */\nconst HANKEL = ((): { a0: Float64Array; a1: Float64Array } => {\n const a0 = new Float64Array(16), a1 = new Float64Array(16);\n a0[0] = 1; a1[0] = 1;\n for (let k = 1; k < 16; k++) {\n const odd = (2 * k - 1) * (2 * k - 1);\n a0[k] = a0[k - 1]! * (0 - odd) / (8 * k);\n a1[k] = a1[k - 1]! * (4 - odd) / (8 * k);\n }\n return { a0, a1 };\n})();\n/** Smallest argument of `besselSquareSum`: there the 16-term expansion's remainder is below 1e-17. */\nconst HANKEL_MINIMUM_ARGUMENT = 300;\n\n/**\n * J₀(x)² + J₁(x)² for x > 0. From x ≥ 300 by the Hankel expansion J_ν(x) = √(2/(πx))·(P_ν cos ω_ν − Q_ν sin ω_ν), ω_ν = x − νπ/2 − π/4,\n * P_ν = Σ(−1)^k a_2k(ν)/x^2k, Q_ν = Σ(−1)^k a_2k+1(ν)/x^2k+1 (DLMF 10.17.3), eight terms each. With ω₁ = ω₀ − π/2,\n * J₁ = √(2/(πx))·(P₁ sin ω₀ + Q₁ cos ω₀). Below 300 by Miller's backward recurrence J_{n−1} = (2n/x)·J_n − J_{n+1} (DLMF 10.6.1;\n * the algorithm, DLMF §3.6(iii)), started at an order above x where J_n is negligible, normalized by J₀ + 2·Σ J_2k = 1\n * (DLMF 10.12.4). Internal.\n */\nexport function besselSquareSum(x: number): number {\n if (!(x > 0) || !Number.isFinite(x)) throw new InvalidConfigurationError(\"J0 and J1 need a positive finite argument.\");\n if (x < HANKEL_MINIMUM_ARGUMENT) return besselSquareSumByRecurrence(x);\n const { a0, a1 } = HANKEL, inverse = 1 / x;\n let p0 = 0, q0 = 0, p1 = 0, q1 = 0, power = 1;\n for (let k = 0; k < 16; k++) {\n const sign = (k >> 1) % 2 === 0 ? 1 : -1;\n if (k % 2 === 0) { p0 += sign * a0[k]! * power; p1 += sign * a1[k]! * power; } else { q0 += sign * a0[k]! * power; q1 += sign * a1[k]! * power; }\n power *= inverse;\n }\n const omega = x - Math.PI / 4, c = Math.cos(omega), s = Math.sin(omega);\n const j0 = p0 * c - q0 * s, j1 = p1 * s + q1 * c;\n return 2 / (Math.PI * x) * (j0 * j0 + j1 * j1);\n}\n/**\n * Miller's backward recurrence for 0 < x < 300 (see `besselSquareSum`). The start order x + 10·∛x + 40 (even) lies far enough in the\n * region where J_n(x) falls faster than exponentially that the start values' error is below double precision at J₀ and J₁; the\n * values are rescaled when they grow large, and normalized before squaring.\n */\nfunction besselSquareSumByRecurrence(x: number): number {\n const start = 2 * Math.ceil((x + 10 * Math.cbrt(x) + 40) / 2);\n let next = 0, current = 1e-100, sum = 0, j1 = 0;\n for (let n = start; n >= 1; n--) {\n const previous = (2 * n / x) * current - next;\n next = current; current = previous;\n if (n - 1 === 1) j1 = current;\n if (n - 1 > 0 && (n - 1) % 2 === 0) sum += 2 * current;\n if (Math.abs(current) > 1e100) { current *= 1e-100; next *= 1e-100; sum *= 1e-100; j1 *= 1e-100; }\n }\n sum += current;\n const j0 = current / sum, j1n = j1 / sum;\n return j0 * j0 + j1n * j1n;\n}\n\n/**\n * Real-space cell energies (2.5): see the module comment. G(Z, φ) = ∫₀^φ [J₀² + J₁²](π·β·Z/cos θ) dθ for cell boundaries at\n * half-integer distances Z (in cells), accumulated along θ for each Z with every needed φ = atan(W/Z) as a panel boundary.\n * The rectangle [0, X] × [0, Y] holds 1/4 − (G(X, atan(Y/X)) + G(Y, atan(X/Y)))/(2π) of the energy. Internal.\n */\nexport function calculateAiryCellEnergiesInRealSpace(beta: number, radius: number, scale = 1): { cells: Float64Array; angularNodes: number } {\n const size = radius + 1, table = new Float64Array(size * size), { nodes, weights } = gaussLegendre(16);\n let angularNodes = 0;\n for (let z = 0; z < size; z++) {\n const Z = z + 0.5, k = Math.PI * beta * Z;\n let sum = 0, t0 = 1, theta0 = 0;\n for (let w = 0; w < size; w++) {\n // Panels equal in t = 1/cos θ, so the phase 2x = 2kt changes by at most 2 radians on each.\n const t1 = Math.hypot(Z, w + 0.5) / Z, theta1 = Math.atan2(w + 0.5, Z), panels = Math.max(1, Math.ceil(scale * k * (t1 - t0)));\n let a = theta0;\n for (let n = 1; n <= panels; n++) {\n const b = n === panels ? theta1 : Math.acos(1 / (t0 + (t1 - t0) * n / panels)), h = b - a;\n let panel = 0;\n for (let g = 0; g < 16; g++) panel += weights[g]! * besselSquareSum(k / Math.cos(a + h * nodes[g]!));\n sum += panel * h;\n a = b;\n }\n angularNodes += 16 * panels;\n table[z * size + w] = sum;\n t0 = t1; theta0 = theta1;\n }\n }\n // Boundaries of cell i along one axis as (half-integer index, weight): the centre cell is twice [0, 1/2].\n const bounds = (i: number): [number, number][] => i === 0 ? [[0, 2]] : [[i, 1], [i - 1, -1]];\n const cells = new Float64Array(size * size);\n for (let j = 0; j < size; j++) for (let i = 0; i < size; i++) {\n let constant = 0, leak = 0;\n for (const [a, wa] of bounds(i)) for (const [b, wb] of bounds(j)) {\n constant += wa * wb;\n leak += wa * wb * (table[a * size + b]! + table[b * size + a]!);\n }\n cells[j * size + i] = constant / 4 - leak / (2 * Math.PI);\n }\n return { cells, angularNodes };\n}\n\n/** Frequency-domain cell energies (2.1; see the module comment). Internal. */\nexport function calculateAiryCellEnergiesInFrequencyDomain(beta: number, radius: number, scale = 1): { cells: Float64Array; radialNodes: number; angularNodes: number } {\n // Bandwidth of the angular and radial integrands: c = π·β·(2R + 1)·√2 (the sinc factors and the highest cosine).\n const c = Math.PI * beta * (2 * radius + 1) * Math.SQRT2, margin = 10 * Math.cbrt(c) + 24;\n const quarter = Math.ceil(scale * (c + margin) / 4), radialNodes = Math.ceil(scale * (c + margin));\n const { nodes, weights } = gaussLegendre(radialNodes), size = radius + 1, cells = new Float64Array(size * size);\n const ca = new Float64Array(size), cb = new Float64Array(size), angularStep = (Math.PI / 2) / quarter;\n // cos θ and sin θ of every angular node, computed once with the same expressions as inside the loop (same values).\n const cosines = new Float64Array(quarter + 1), sines = new Float64Array(quarter + 1);\n for (let k = 0; k <= quarter; k++) { const theta = k * angularStep; cosines[k] = Math.cos(theta); sines[k] = Math.sin(theta); }\n for (let r = 0; r < radialNodes; r++) {\n const t = nodes[r]!, rho = 1 - t * t;\n // H(1 − t²) without cancellation: acos(1 − t²) = 2·asin(t/√2), ρ·√(1 − ρ²) = ρ·t·√(2 − t²).\n const otf = (2 / Math.PI) * (2 * Math.asin(t / Math.SQRT2) - rho * t * Math.sqrt(2 - t * t));\n // ∫₀¹ g(ρ) dρ = ∫₀¹ g(1 − t²)·2t dt; the 4 is the four symmetric quadrants of the angular trapezoid.\n const radialWeight = weights[r]! * 2 * t * rho * otf * 4 * angularStep;\n for (let k = 0; k <= quarter; k++) {\n const x = beta * rho * cosines[k]!, y = beta * rho * sines[k]!;\n const w = radialWeight * (k === 0 || k === quarter ? 0.5 : 1) * sinc(x) * sinc(y);\n // cos(2π·i·x) and cos(2π·j·y) by the Chebyshev recurrence.\n const cx = Math.cos(2 * Math.PI * x), cy = Math.cos(2 * Math.PI * y);\n ca[0] = 1; cb[0] = 1;\n if (size > 1) { ca[1] = cx; cb[1] = cy; }\n for (let i = 2; i < size; i++) { ca[i] = 2 * cx * ca[i - 1]! - ca[i - 2]!; cb[i] = 2 * cy * cb[i - 1]! - cb[i - 2]!; }\n for (let j = 0; j < size; j++) {\n const wj = w * cb[j]!;\n for (let i = 0; i < size; i++) { const o = j * size + i; cells[o] = cells[o]! + wj * ca[i]!; }\n }\n }\n }\n const area = beta * beta;\n for (let i = 0; i < cells.length; i++) cells[i] = cells[i]! * area;\n return { cells, radialNodes, angularNodes: 4 * quarter };\n}\n\n/**\n * Creates a sampled lens PSF profile for an ideal diffraction-limited lens with a circular pupil: one\n * unit-sum Airy kernel per wavelength on one shared (2R+1)² grid, with the truncated energy reported per\n * wavelength. The profile declares the given focal length, f-number and focus exactly, and the field axes\n * ±`fieldHalfExtentMm` with the same kernel at every field node.\n * @param input - See `CreateDiffractionLimitedPsfProfileInput`.\n * @returns The profile and its diffraction record. An approximation; not a measured lens.\n * @see docs/PSF_FOUNDATION.md, \"Diffraction-limited sampled profile (2.1)\".\n */\nexport function createDiffractionLimitedPsfProfile(input: CreateDiffractionLimitedPsfProfileInput): CalculationResult<DiffractionLimitedPsfProfile> {\n const r = requireAllowlistedRecord(input, [\"aperture\", \"focalLengthMm\", \"apertureFNumber\", \"focus\", \"wavelengthsNm\", \"samplePitchMicrometers\",\n \"kernelRadiusSamples\", \"fieldHalfExtentMm\", \"profileId\"], \"Invalid diffraction-limited PSF profile input.\");\n if (r.aperture !== \"circular\") throw new InvalidConfigurationError(\"aperture must be \\\"circular\\\".\");\n const focalLengthMm = positive(r.focalLengthMm, \"focalLengthMm\"), fNumber = positive(r.apertureFNumber, \"apertureFNumber\");\n const pitch = positive(r.samplePitchMicrometers, \"samplePitchMicrometers\");\n const L = DIFFRACTION_LIMITED_PSF_PROFILE_LIMITS;\n const radius = r.kernelRadiusSamples;\n if (typeof radius !== \"number\" || !Number.isSafeInteger(radius) || radius < 0 || radius > L.maximumKernelRadiusSamples) {\n throw new InvalidConfigurationError(\"kernelRadiusSamples must be an integer from 0 to \" + L.maximumKernelRadiusSamples + \".\");\n }\n const focus = requireAllowlistedRecord(r.focus, [\"kind\", \"distanceM\"], \"Invalid focus.\");\n let focusDiopters: number, distanceMm: number;\n if (focus.kind === \"infinity\") {\n if (focus.distanceM !== undefined) throw new InvalidConfigurationError(\"An infinity focus has no distanceM.\");\n focusDiopters = 0; distanceMm = focalLengthMm;\n } else if (focus.kind === \"finite\") {\n const distanceM = positive(focus.distanceM, \"focus.distanceM\");\n focusDiopters = 1 / distanceM;\n distanceMm = calculateThinLensImageDistance({ focalLengthMm, objectDistanceM: distanceM }).value.imageDistanceMm;\n } else throw new InvalidConfigurationError(\"focus.kind must be finite or infinity.\");\n const field = requireAllowlistedRecord(r.fieldHalfExtentMm, [\"x\", \"y\"], \"Invalid fieldHalfExtentMm.\");\n const fieldX = positive(field.x, \"fieldHalfExtentMm.x\"), fieldY = positive(field.y, \"fieldHalfExtentMm.y\");\n const list = r.wavelengthsNm;\n if (!Array.isArray(list) || list.length < 1 || list.length > L.maximumWavelengths) throw new InvalidConfigurationError(\"wavelengthsNm must list 1 to 64 wavelengths.\");\n const wavelengths = (list as unknown[]).map((value, index) => positive(value, \"wavelengthsNm[\" + index + \"]\"));\n for (let i = 1; i < wavelengths.length; i++) if (!(wavelengths[i]! > wavelengths[i - 1]!)) throw new InvalidConfigurationError(\"wavelengthsNm must be strictly increasing.\");\n if (typeof r.profileId !== \"string\" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(r.profileId)) throw new InvalidConfigurationError(\"profileId must be a public opaque ID.\");\n\n const pupilDiameterMm = focalLengthMm / fNumber, workingFNumber = distanceMm / pupilDiameterMm, size = 2 * radius + 1;\n let maximumRadialNodes = 0, maximumAngularNodes = 0, maximumTruncated = 0;\n const records: DiffractionLimitedPsfWavelength[] = [], kernels: number[][] = [], realSpaceWavelengthsNm: number[] = [];\n for (const nm of wavelengths) {\n const lambdaN = nm / 1000 * workingFNumber, cutoff = 1 / lambdaN;\n const airy = calculateAiryCellEnergies(pitch * cutoff, radius);\n if (airy.realSpace) realSpaceWavelengthsNm.push(nm);\n maximumRadialNodes = Math.max(maximumRadialNodes, airy.radialNodes); maximumAngularNodes = Math.max(maximumAngularNodes, airy.angularNodes);\n const values: number[] = new Array(size * size);\n let captured = 0;\n for (let ky = 0; ky < size; ky++) for (let kx = 0; kx < size; kx++) {\n const value = airy.cells[Math.abs(ky - radius) * (radius + 1) + Math.abs(kx - radius)]!;\n // Every cell energy of a non-negative PSF is positive; a negative value would be a quadrature failure.\n if (!(value > -1e-13)) throw new InvalidConfigurationError(\"Diffraction cell integration failed to converge.\");\n values[ky * size + kx] = Math.max(0, value);\n captured += values[ky * size + kx]!;\n }\n if (!(captured > 0 && captured <= 1 + 1e-9)) throw new InvalidConfigurationError(\"Diffraction cell integration failed to converge.\");\n const truncated = Math.max(0, 1 - captured);\n maximumTruncated = Math.max(maximumTruncated, truncated);\n const kernel = values.map((v) => v / captured);\n kernels.push(kernel);\n records.push({ wavelengthNm: nm, cutoffFrequencyCyclesPerMicrometer: cutoff, firstZeroRadiusMicrometers: AIRY_FIRST_ZERO_PER_LAMBDA_N * lambdaN,\n capturedEnergyFraction: captured, truncatedEnergyFraction: truncated, centreSampleFraction: kernel[radius * size + radius]! });\n }\n const uncertainty = { kind: \"not-quantified\" as const, limitation: \"Ideal diffraction-limited model; no measured lens or quadrature error bound.\" };\n const nodes = [-fieldX, fieldX].flatMap((fx) => [-fieldY, fieldY].flatMap((fy) => wavelengths.map((nm, index) => ({\n nodeId: \"airy-\" + (fx < 0 ? \"xm\" : \"xp\") + \"-\" + (fy < 0 ? \"ym\" : \"yp\") + \"-\" + index,\n coordinate: { focalLengthMm, focusDiopters, apertureFNumber: fNumber, fieldXmm: fx, fieldYmm: fy, wavelengthNm: nm, signedDefocusImagePlaneMicrometers: 0 },\n kernel: { widthSamples: size, heightSamples: size, samplePitchMicrometersX: pitch, samplePitchMicrometersY: pitch, centerSampleX: radius, centerSampleY: radius,\n normalizedIntensity: kernels[index]! },\n bestFocusImagePlaneOffsetMicrometers: 0, relativePupilThroughputFactor: 1, evidence: EVIDENCE, uncertainty }))));\n const profile = parseLensSampledPsfProfile({ schemaVersion: \"0.1.0\", profileId: r.profileId, profileVersion: DIFFRACTION_LIMITED_PSF_PROFILE_MODEL.modelVersion,\n scientificStatus: \"approximation\", opticalDomain: \"lens-primary-optical-path-only\", coordinateSystem: \"image-plane-metric\", fieldAxes: \"+X right, +Y up\",\n kernelEnergyNormalization: \"unit-energy-shape\", interpolation: \"bounded-regular-grid-multilinear\", throughputOwnership: \"separate-relative-pupil-throughput-factor\",\n responseIncludes: { diffraction: true, aberration: false, defocus: false, pupilClippingShape: false },\n sensorOpticalStackIncluded: false, sensorSamplingIncluded: false, reconstructionIncluded: false, strayLightIncluded: false,\n axes: { focalLengthMm: [focalLengthMm], focusDiopters: [focusDiopters], apertureFNumber: [fNumber], fieldXmm: [-fieldX, fieldX], fieldYmm: [-fieldY, fieldY],\n wavelengthNm: wavelengths, signedDefocusImagePlaneMicrometers: [0] },\n nodes, evidence: EVIDENCE, limitations: [...LIMITATIONS] });\n return approximationResult({ profile, model: DIFFRACTION_LIMITED_PSF_PROFILE_MODEL, pupilDiameterMm, pupilToImageDistanceMm: distanceMm, workingFNumber,\n kernelRadiusSamples: radius, samplePitchMicrometers: pitch, wavelengths: records, maximumTruncatedEnergyFraction: maximumTruncated,\n quadrature: realSpaceWavelengthsNm.length === 0 ? { method: \"polar-frequency-domain-trapezoid-gauss-legendre\" as const, maximumRadialNodes, maximumAngularNodes } :\n { method: realSpaceWavelengthsNm.length === wavelengths.length ? \"real-space-encircled-energy-gauss-legendre\" as const : \"frequency-domain-and-real-space\" as const,\n maximumRadialNodes, maximumAngularNodes, realSpaceWavelengthsNm } },\n DIFFRACTION_LIMITED_PSF_PROFILE_MODEL.modelId, DIFFRACTION_LIMITED_PSF_PROFILE_MODEL.modelVersion, [...LIMITATIONS]);\n}\n"]}
|
|
@@ -399,7 +399,7 @@ function transmissionEvidence(transmission) {
|
|
|
399
399
|
return transmission
|
|
400
400
|
.samples.evidence;
|
|
401
401
|
}
|
|
402
|
-
const UNPOLARIZED = Object.freeze({
|
|
402
|
+
const UNPOLARIZED = /* @__PURE__ */ Object.freeze({
|
|
403
403
|
degreeOfLinearPolarization: 0,
|
|
404
404
|
angleDegrees: 0
|
|
405
405
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"front-of-lens-filter.js","sourceRoot":"","sources":["../../src/optics/front-of-lens-filter.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Generic filters that screw onto the front of the lens.\n *\n * Schema 0.1.0 is explicitly unbranded and unpolarized. It models only passive transmission in front\n * of the lens. It does not cover reflections between stacked filters, flare or ghosting, or filters\n * that change wavelength.\n *\n * Schema 0.2.0 adds one polarizing kind: a linear (partial) polarizer. It has a principal\n * transmittance k1, an extinction ratio k1/k2 and a transmission-axis angle. Polarization is carried\n * as linear Stokes parameters (S0, S1, S2). Filters are applied in order using the Mueller matrix of\n * a linear diattenuator (Gil, arXiv:2002.04105, eqs. 134-135, free; Malus's law: OpenStax University\n * Physics Vol. 3, sec. 1.7, free. Also see: Chipman, Handbook of Optics vol. I ch. 22, 3rd ed., 2010;\n * Goldstein, Polarized Light, 3rd ed., ch. 4-5; Born & Wolf, Principles of Optics, sec. 1.4.2):\n * T = (k1 + k2)/2 + (k1 - k2)/2 * P * cos(2 (psi - theta))\n * Here P is the incident light's degree of linear polarization, psi its polarization angle and theta\n * the filter axis angle.\n * - For P = 1 this is Malus's law: k1 cos^2(psi - theta) + k2 sin^2(psi - theta).\n * - For unpolarized light it is (k1 + k2)/2, about half of k1.\n * Not modelled: circular polarization, retardance (for example the quarter-wave plate in a circular\n * polarizer), dependence on the angle of incidence, and depolarization.\n * @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceBackedFact,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport {\n parseSpectralWavelengthBasis,\n type SpectralWavelengthBasis\n} from \"../core/spectral.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport { requireInputKeys, rejectUnknownFields, rejectUnknownVariantFields, UNCERTAINTY_VARIANT_FIELDS } from \"../core/record-validation.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport const FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION =\n \"0.1.0\" as const;\n/** Schema that also allows the `linear-polarizer` transmission kind. */\nexport const FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION =\n \"0.2.0\" as const;\n\nexport type FrontOfLensFilterProfileSchemaVersion =\n | typeof FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION\n | typeof FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION;\n\n/** Partially linearly polarized light: degree P in [0, 1] and polarization angle psi. */\nexport interface LinearPolarizationState {\n /** Degree of linear polarization P in [0, 1]; 0 is unpolarized. */\n degreeOfLinearPolarization: number;\n /** Electric-field polarization angle, degrees counter-clockwise from image +X. */\n angleDegrees: number;\n}\n\nexport type FrontOfLensFilterScientificStatus =\n | \"calibrated\"\n | \"approximation\";\n\nexport type FrontOfLensFilterUncertainty =\n | {\n kind: \"relative\";\n fraction: number;\n basis: string;\n }\n | {\n kind: \"not-quantified\";\n limitation: string;\n };\n\nexport interface FrontOfLensFilterSpectralSample {\n wavelengthNanometers: number;\n linearTransmissionFactor: number;\n}\n\nexport type FrontOfLensFilterTransmissionModel =\n | {\n kind: \"neutral-linear-transmission\";\n linearTransmissionFactor:\n EvidenceBackedFact<number>;\n }\n | {\n kind: \"neutral-optical-density\";\n opticalDensityBase10:\n EvidenceBackedFact<number>;\n }\n | {\n kind: \"spectral-transmission\";\n samples:\n EvidenceBackedFact<\n readonly FrontOfLensFilterSpectralSample[]\n >;\n }\n | {\n /** Schema 0.2.0 only. Neutral (wavelength-independent) within the declared range. */\n kind: \"linear-polarizer\";\n /** k1: intensity transmittance for light polarized along the transmission axis, (0, 1]. */\n principalTransmittance:\n EvidenceBackedFact<number>;\n /** k1 / k2. Finite and >= 1. Use a large finite ratio for a near-ideal polarizer. */\n extinctionRatio:\n EvidenceBackedFact<number>;\n /** Transmission-axis angle as mounted, degrees counter-clockwise from image +X. */\n transmissionAxisDegrees: number;\n };\n\nexport interface FrontOfLensFilterProfile {\n schemaVersion:\n FrontOfLensFilterProfileSchemaVersion;\n filterId: string;\n profileVersion: string;\n identityScope:\n \"photivra-generic-unbranded\";\n position: \"front-of-lens\";\n scientificStatus:\n FrontOfLensFilterScientificStatus;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n wavelengthRangeNanometers: {\n minimum: number;\n maximum: number;\n };\n transmission:\n FrontOfLensFilterTransmissionModel;\n uncertainty:\n FrontOfLensFilterUncertainty;\n /** True exactly when the transmission kind is `linear-polarizer` (schema 0.2.0). */\n polarizationModeled: boolean;\n wavelengthChangingBehaviorModeled:\n false;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface ResolveFrontOfLensFilterTransmissionInput {\n profile: FrontOfLensFilterProfile;\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n /** Incident polarization; omitted means unpolarized. */\n incidentPolarization?: LinearPolarizationState;\n}\n\nexport interface ResolvedFrontOfLensFilterTransmission {\n schemaVersion:\n FrontOfLensFilterProfileSchemaVersion;\n filterId: string;\n profileVersion: string;\n identityScope:\n \"photivra-generic-unbranded\";\n position: \"front-of-lens\";\n scientificStatus:\n FrontOfLensFilterScientificStatus;\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n transmissionKind:\n FrontOfLensFilterTransmissionModel[\"kind\"];\n /** Intensity transmittance for the declared incident polarization. */\n linearTransmissionFactor: number;\n attenuationStops: number;\n opticalDensityBase10: number;\n polarizationModeled: boolean;\n incidentPolarization: LinearPolarizationState;\n transmittedPolarization: LinearPolarizationState;\n wavelengthChangingBehaviorModeled:\n false;\n lensTransmissionIncluded: false;\n sensorOpticalStackIncluded: false;\n fieldThroughputIncluded: false;\n uncertainty:\n FrontOfLensFilterUncertainty;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface ComposeFrontOfLensFilterTransmissionInput {\n /** Filters in light-path order (scene side first). */\n filters:\n readonly FrontOfLensFilterProfile[];\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n /** Incident scene polarization; omitted means unpolarized. */\n incidentPolarization?: LinearPolarizationState;\n}\n\nexport interface ComposedFrontOfLensFilterTransmission {\n schemaVersion:\n FrontOfLensFilterProfileSchemaVersion;\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n appliedFilterCount: number;\n components:\n readonly ResolvedFrontOfLensFilterTransmission[];\n combinedLinearTransmissionFactor:\n number;\n combinedAttenuationStops: number;\n scientificStatus:\n FrontOfLensFilterScientificStatus;\n uncertaintyPropagation:\n \"not-propagated\";\n uncertaintyLimitation: string;\n compositionModel:\n | \"independent-multiplicative-unpolarized-transmission-no-inter-filter-reflections\"\n | \"ordered-linear-stokes-mueller-no-inter-filter-reflections\";\n polarizationModeled: boolean;\n incidentPolarization: LinearPolarizationState;\n transmittedPolarization: LinearPolarizationState;\n wavelengthChangingBehaviorModeled:\n false;\n lensTransmissionIncluded: false;\n sensorOpticalStackIncluded: false;\n fieldThroughputIncluded: false;\n}\n\nfunction requireRecord(\n value: unknown,\n path: string,\n allowedKeys: readonly string[] | null\n): UnknownRecord {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be an object.\"\n );\n }\n if (allowedKeys !== null) rejectUnknownFields(value, allowedKeys, path);\n return value as UnknownRecord;\n}\n\nfunction requireNonEmptyString(\n value: unknown,\n path: string\n): string {\n if (\n typeof value !== \"string\" ||\n value.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n path + \" must be a non-empty string.\"\n );\n }\n return value.trim();\n}\n\nfunction requireFinite(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be finite.\"\n );\n }\n return value;\n}\n\nfunction requirePositiveFinite(\n value: unknown,\n path: string\n): number {\n const parsed = requireFinite(\n value,\n path\n );\n if (parsed <= 0) {\n throw new InvalidConfigurationError(\n path +\n \" must be greater than zero.\"\n );\n }\n return parsed;\n}\n\nfunction requireNonNegativeFinite(\n value: unknown,\n path: string\n): number {\n const parsed = requireFinite(\n value,\n path\n );\n if (parsed < 0) {\n throw new InvalidConfigurationError(\n path +\n \" must be greater than or equal to zero.\"\n );\n }\n return parsed;\n}\n\nfunction requirePassiveTransmission(\n value: unknown,\n path: string\n): number {\n const parsed = requirePositiveFinite(\n value,\n path\n );\n if (parsed > 1) {\n throw new InvalidConfigurationError(\n path +\n \" must be less than or equal to one for a passive filter.\"\n );\n }\n return parsed;\n}\n\nfunction parseRange(\n value: unknown,\n path: string\n): {\n minimum: number;\n maximum: number;\n} {\n const record = requireRecord(\n value,\n path, [\"minimum\", \"maximum\"]\n );\n const minimum =\n requirePositiveFinite(\n record.minimum,\n path + \".minimum\"\n );\n const maximum =\n requirePositiveFinite(\n record.maximum,\n path + \".maximum\"\n );\n if (minimum > maximum) {\n throw new InvalidConfigurationError(\n path +\n \".minimum must be less than or equal to maximum.\"\n );\n }\n return {\n minimum,\n maximum\n };\n}\n\nfunction parseResolvedBasis(\n value: unknown,\n path: string\n): Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n> {\n const parsed =\n parseSpectralWavelengthBasis(\n value,\n path\n );\n if (parsed === \"unspecified\") {\n throw new InvalidConfigurationError(\n path +\n ' must resolve to \"air\" or \"vacuum\".'\n );\n }\n return parsed;\n}\n\nfunction parseScientificStatus(\n value: unknown,\n path: string\n): FrontOfLensFilterScientificStatus {\n if (\n value !== \"calibrated\" &&\n value !== \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value;\n}\n\nfunction parseUncertainty(\n value: unknown,\n path: string\n): FrontOfLensFilterUncertainty {\n const record = requireRecord(\n value,\n path, null\n );\n rejectUnknownVariantFields(record, \"kind\", UNCERTAINTY_VARIANT_FIELDS, path);\n\n if (record.kind === \"relative\") {\n const fraction =\n requireNonNegativeFinite(\n record.fraction,\n path + \".fraction\"\n );\n if (fraction > 1) {\n throw new InvalidConfigurationError(\n path +\n \".fraction must be less than or equal to one.\"\n );\n }\n return {\n kind: \"relative\",\n fraction,\n basis:\n requireNonEmptyString(\n record.basis,\n path + \".basis\"\n )\n };\n }\n\n if (\n record.kind ===\n \"not-quantified\"\n ) {\n return {\n kind: \"not-quantified\",\n limitation:\n requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseLimitations(\n value: unknown,\n path: string\n): readonly string[] {\n if (!Array.isArray(value)) {\n throw new InvalidConfigurationError(\n path + \" must be an array.\"\n );\n }\n const parsed = value.map(\n (entry, index) =>\n requireNonEmptyString(\n entry,\n path +\n \"[\" +\n index +\n \"]\"\n )\n );\n if (\n new Set(parsed).size !==\n parsed.length\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must not contain duplicates.\"\n );\n }\n return parsed;\n}\n\nfunction parseReusableNumericEvidence(\n value: unknown,\n path: string\n): readonly EvidenceProvenance[] {\n const evidence =\n parseEvidenceList(\n value,\n path\n );\n if (\n evidence.some(\n (entry) =>\n entry.reuseStatus ===\n \"factual-reference-only\"\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \" for embedded numeric filter data must be reusable-data or photivra-owned.\"\n );\n }\n return evidence;\n}\n\nfunction parseSpectralSamples(\n value: unknown,\n path: string\n): readonly FrontOfLensFilterSpectralSample[] {\n if (\n !Array.isArray(value) ||\n value.length < 2\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must contain at least two samples.\"\n );\n }\n\n let previous =\n Number.NEGATIVE_INFINITY;\n return value.map(\n (entry, index) => {\n const samplePath =\n path +\n \"[\" +\n index +\n \"]\";\n const record =\n requireRecord(\n entry,\n samplePath, [\"wavelengthNanometers\", \"linearTransmissionFactor\"]\n );\n const wavelengthNanometers =\n requirePositiveFinite(\n record.wavelengthNanometers,\n samplePath +\n \".wavelengthNanometers\"\n );\n if (\n wavelengthNanometers <=\n previous\n ) {\n throw new InvalidConfigurationError(\n path +\n \" wavelengths must be strictly increasing.\"\n );\n }\n previous =\n wavelengthNanometers;\n return {\n wavelengthNanometers,\n linearTransmissionFactor:\n requirePassiveTransmission(\n record.linearTransmissionFactor,\n samplePath +\n \".linearTransmissionFactor\"\n )\n };\n }\n );\n}\n\nfunction parseTransmission(\n value: unknown,\n path: string,\n polarizerAllowed: boolean\n): FrontOfLensFilterTransmissionModel {\n const record = requireRecord(\n value,\n path, null\n );\n rejectUnknownVariantFields(record, \"kind\", {\n \"neutral-linear-transmission\": [\"kind\", \"linearTransmissionFactor\"],\n \"neutral-optical-density\": [\"kind\", \"opticalDensityBase10\"],\n \"spectral-transmission\": [\"kind\", \"samples\"],\n \"linear-polarizer\": [\"kind\", \"principalTransmittance\", \"extinctionRatio\", \"transmissionAxisDegrees\"]\n }, path);\n\n if (record.kind === \"linear-polarizer\") {\n if (!polarizerAllowed) {\n throw new InvalidConfigurationError(\n path + '.kind \"linear-polarizer\" requires schemaVersion \"' +\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION + '\".'\n );\n }\n const principal = requireRecord(\n record.principalTransmittance,\n path + \".principalTransmittance\", [\"value\", \"evidence\"]\n );\n const extinction = requireRecord(\n record.extinctionRatio,\n path + \".extinctionRatio\", [\"value\", \"evidence\"]\n );\n const ratio = requireFinite(\n extinction.value,\n path + \".extinctionRatio.value\"\n );\n if (ratio < 1) {\n throw new InvalidConfigurationError(\n path + \".extinctionRatio.value must be at least one.\"\n );\n }\n return {\n kind: \"linear-polarizer\",\n principalTransmittance: {\n value: requirePassiveTransmission(\n principal.value,\n path + \".principalTransmittance.value\"\n ),\n evidence: parseEvidenceList(\n principal.evidence,\n path + \".principalTransmittance.evidence\"\n )\n },\n extinctionRatio: {\n value: ratio,\n evidence: parseEvidenceList(\n extinction.evidence,\n path + \".extinctionRatio.evidence\"\n )\n },\n transmissionAxisDegrees: requireFinite(\n record.transmissionAxisDegrees,\n path + \".transmissionAxisDegrees\"\n )\n };\n }\n\n if (\n record.kind ===\n \"neutral-linear-transmission\"\n ) {\n const fact = requireRecord(\n record.linearTransmissionFactor,\n path +\n \".linearTransmissionFactor\", [\"value\", \"evidence\"]\n );\n return {\n kind:\n \"neutral-linear-transmission\",\n linearTransmissionFactor: {\n value:\n requirePassiveTransmission(\n fact.value,\n path +\n \".linearTransmissionFactor.value\"\n ),\n evidence:\n parseEvidenceList(\n fact.evidence,\n path +\n \".linearTransmissionFactor.evidence\"\n )\n }\n };\n }\n\n if (\n record.kind ===\n \"neutral-optical-density\"\n ) {\n const fact = requireRecord(\n record.opticalDensityBase10,\n path +\n \".opticalDensityBase10\", [\"value\", \"evidence\"]\n );\n return {\n kind:\n \"neutral-optical-density\",\n opticalDensityBase10: {\n value:\n requireNonNegativeFinite(\n fact.value,\n path +\n \".opticalDensityBase10.value\"\n ),\n evidence:\n parseEvidenceList(\n fact.evidence,\n path +\n \".opticalDensityBase10.evidence\"\n )\n }\n };\n }\n\n if (\n record.kind ===\n \"spectral-transmission\"\n ) {\n const fact = requireRecord(\n record.samples,\n path + \".samples\", [\"value\", \"evidence\"]\n );\n return {\n kind:\n \"spectral-transmission\",\n samples: {\n value:\n parseSpectralSamples(\n fact.value,\n path +\n \".samples.value\"\n ),\n evidence:\n parseReusableNumericEvidence(\n fact.evidence,\n path +\n \".samples.evidence\"\n )\n }\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\n/**\n * Parses one generic front-of-lens transmission filter.\n *\n * Schema 0.1.0 is explicitly unbranded and unpolarized. It models only\n * passive transmission in front of the lens. It does not cover reflections\n * between stacked filters, polarization, flare or ghosting, or filters that\n * change wavelength.\n */\nexport function parseFrontOfLensFilterProfile(\n value: unknown\n): FrontOfLensFilterProfile {\n const record = requireRecord(\n value,\n \"frontOfLensFilterProfile\", [\"schemaVersion\", \"identityScope\", \"position\", \"wavelengthChangingBehaviorModeled\", \"polarizationModeled\", \"scientificStatus\", \"uncertainty\", \"wavelengthRangeNanometers\", \"transmission\", \"filterId\", \"profileVersion\", \"wavelengthBasis\", \"evidence\", \"limitations\"]\n );\n\n if (\n record.schemaVersion !==\n FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION &&\n record.schemaVersion !==\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'frontOfLensFilterProfile.schemaVersion must be \"' +\n FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION +\n '\" or \"' +\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n const schemaVersion =\n record.schemaVersion as FrontOfLensFilterProfileSchemaVersion;\n if (\n record.identityScope !==\n \"photivra-generic-unbranded\"\n ) {\n throw new InvalidConfigurationError(\n 'frontOfLensFilterProfile.identityScope must be \"photivra-generic-unbranded\".'\n );\n }\n if (\n record.position !==\n \"front-of-lens\"\n ) {\n throw new InvalidConfigurationError(\n 'frontOfLensFilterProfile.position must be \"front-of-lens\".'\n );\n }\n if (\n record.wavelengthChangingBehaviorModeled !==\n false ||\n (schemaVersion ===\n FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION &&\n record.polarizationModeled !== false)\n ) {\n throw new InvalidConfigurationError(\n \"frontOfLensFilterProfile must explicitly keep polarization and wavelength-changing behavior unmodeled in schema 0.1.0.\"\n );\n }\n\n const status =\n parseScientificStatus(\n record.scientificStatus,\n \"frontOfLensFilterProfile.scientificStatus\"\n );\n const uncertainty =\n parseUncertainty(\n record.uncertainty,\n \"frontOfLensFilterProfile.uncertainty\"\n );\n\n if (\n status === \"calibrated\" &&\n uncertainty.kind !==\n \"relative\"\n ) {\n throw new InvalidConfigurationError(\n \"A calibrated filter profile requires quantified relative uncertainty.\"\n );\n }\n\n const range =\n parseRange(\n record.wavelengthRangeNanometers,\n \"frontOfLensFilterProfile.wavelengthRangeNanometers\"\n );\n const transmission =\n parseTransmission(\n record.transmission,\n \"frontOfLensFilterProfile.transmission\",\n schemaVersion ===\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION\n );\n const polarizationModeled =\n transmission.kind === \"linear-polarizer\";\n if (record.polarizationModeled !== polarizationModeled) {\n throw new InvalidConfigurationError(\n \"frontOfLensFilterProfile.polarizationModeled must be true exactly for a linear-polarizer transmission.\"\n );\n }\n\n if (\n transmission.kind ===\n \"spectral-transmission\"\n ) {\n const samples =\n transmission.samples.value;\n if (\n samples[0]!\n .wavelengthNanometers >\n range.minimum ||\n samples[\n samples.length - 1\n ]!.wavelengthNanometers <\n range.maximum\n ) {\n throw new InvalidConfigurationError(\n \"Spectral filter samples must cover the declared wavelength range.\"\n );\n }\n }\n\n return {\n schemaVersion,\n filterId:\n requireNonEmptyString(\n record.filterId,\n \"frontOfLensFilterProfile.filterId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"frontOfLensFilterProfile.profileVersion\"\n ),\n identityScope:\n \"photivra-generic-unbranded\",\n position:\n \"front-of-lens\",\n scientificStatus:\n status,\n wavelengthBasis:\n parseResolvedBasis(\n record.wavelengthBasis,\n \"frontOfLensFilterProfile.wavelengthBasis\"\n ),\n wavelengthRangeNanometers:\n range,\n transmission,\n uncertainty,\n polarizationModeled,\n wavelengthChangingBehaviorModeled:\n false,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"frontOfLensFilterProfile.evidence\"\n ),\n limitations:\n parseLimitations(\n record.limitations,\n \"frontOfLensFilterProfile.limitations\"\n )\n };\n}\n\nfunction interpolateSpectralTransmission(\n samples:\n readonly FrontOfLensFilterSpectralSample[],\n wavelengthNanometers: number\n): number {\n const first =\n samples[0]!;\n const last =\n samples[\n samples.length - 1\n ]!;\n\n if (\n wavelengthNanometers ===\n first.wavelengthNanometers\n ) {\n return first\n .linearTransmissionFactor;\n }\n\n for (\n let index = 1;\n index < samples.length;\n index += 1\n ) {\n const right =\n samples[index]!;\n if (\n wavelengthNanometers <=\n right.wavelengthNanometers\n ) {\n const left =\n samples[\n index - 1\n ]!;\n if (\n wavelengthNanometers ===\n right.wavelengthNanometers\n ) {\n return right\n .linearTransmissionFactor;\n }\n const phase =\n (wavelengthNanometers -\n left.wavelengthNanometers) /\n (right.wavelengthNanometers -\n left.wavelengthNanometers);\n return (\n left\n .linearTransmissionFactor +\n phase *\n (right\n .linearTransmissionFactor -\n left\n .linearTransmissionFactor)\n );\n }\n }\n\n return last\n .linearTransmissionFactor;\n}\n\nfunction scientificWavelength(\n value: number\n): number {\n if (\n !Number.isFinite(value) ||\n value <= 0\n ) {\n throw new InvalidScientificInputError(\n \"wavelengthNanometers must be finite and greater than zero.\"\n );\n }\n return value;\n}\n\nfunction transmissionEvidence(\n transmission:\n FrontOfLensFilterTransmissionModel\n): readonly EvidenceProvenance[] {\n if (\n transmission.kind ===\n \"neutral-linear-transmission\"\n ) {\n return transmission\n .linearTransmissionFactor\n .evidence;\n }\n if (\n transmission.kind ===\n \"neutral-optical-density\"\n ) {\n return transmission\n .opticalDensityBase10\n .evidence;\n }\n if (transmission.kind === \"linear-polarizer\") {\n return [\n ...transmission.principalTransmittance.evidence,\n ...transmission.extinctionRatio.evidence\n ];\n }\n return transmission\n .samples.evidence;\n}\n\n/** Linear Stokes vector (S0, S1, S2); circular S3 is not modeled. */\ninterface LinearStokes {\n s0: number;\n s1: number;\n s2: number;\n}\n\nconst UNPOLARIZED: LinearPolarizationState = Object.freeze({\n degreeOfLinearPolarization: 0,\n angleDegrees: 0\n});\n\nfunction parsePolarizationState(\n value: LinearPolarizationState | undefined,\n path: string\n): LinearPolarizationState {\n if (value === undefined) {\n return { ...UNPOLARIZED };\n }\n if (typeof value !== \"object\" || value === null) {\n throw new InvalidConfigurationError(path + \" must be an object.\");\n }\n const degree = value.degreeOfLinearPolarization;\n const angle = value.angleDegrees;\n if (\n typeof degree !== \"number\" ||\n !Number.isFinite(degree) ||\n degree < 0 ||\n degree > 1\n ) {\n throw new InvalidScientificInputError(\n path + \".degreeOfLinearPolarization must lie in [0, 1].\"\n );\n }\n if (typeof angle !== \"number\" || !Number.isFinite(angle)) {\n throw new InvalidScientificInputError(\n path + \".angleDegrees must be finite.\"\n );\n }\n return { degreeOfLinearPolarization: degree, angleDegrees: angle };\n}\n\nfunction stokesFromState(state: LinearPolarizationState): LinearStokes {\n const twice = (2 * state.angleDegrees * Math.PI) / 180;\n return {\n s0: 1,\n s1: state.degreeOfLinearPolarization * Math.cos(twice),\n s2: state.degreeOfLinearPolarization * Math.sin(twice)\n };\n}\n\nfunction stateFromStokes(stokes: LinearStokes): LinearPolarizationState {\n const polarized = Math.hypot(stokes.s1, stokes.s2);\n const degree = Math.min(1, polarized / stokes.s0);\n if (degree === 0) {\n return { ...UNPOLARIZED };\n }\n let angle = (Math.atan2(stokes.s2, stokes.s1) * 90) / Math.PI;\n if (angle < 0) angle += 180;\n return { degreeOfLinearPolarization: degree, angleDegrees: angle };\n}\n\n/**\n * Mueller matrix of a linear diattenuator (principal intensity transmittances k1 along the axis\n * and k2 across it, axis at theta) applied to a linear Stokes vector.\n */\nfunction applyLinearPolarizer(\n stokes: LinearStokes,\n k1: number,\n k2: number,\n axisDegrees: number\n): LinearStokes {\n const twice = (2 * axisDegrees * Math.PI) / 180;\n const c = Math.cos(twice);\n const sn = Math.sin(twice);\n const sum = (k1 + k2) / 2;\n const difference = (k1 - k2) / 2;\n const geometric = Math.sqrt(k1 * k2);\n return {\n s0: sum * stokes.s0 + difference * (c * stokes.s1 + sn * stokes.s2),\n s1:\n difference * c * stokes.s0 +\n (sum * c * c + geometric * sn * sn) * stokes.s1 +\n (sum - geometric) * c * sn * stokes.s2,\n s2:\n difference * sn * stokes.s0 +\n (sum - geometric) * c * sn * stokes.s1 +\n (sum * sn * sn + geometric * c * c) * stokes.s2\n };\n}\n\ninterface ResolvedComponent {\n resolved: ResolvedFrontOfLensFilterTransmission;\n outgoing: LinearStokes;\n}\n\nfunction resolveComponent(\n input: ResolveFrontOfLensFilterTransmissionInput,\n incoming: LinearStokes\n): ResolvedComponent {\n const profile =\n parseFrontOfLensFilterProfile(\n input.profile\n );\n const wavelength =\n scientificWavelength(\n input.wavelengthNanometers\n );\n\n if (\n input.wavelengthBasis !==\n profile.wavelengthBasis\n ) {\n throw new InvalidScientificInputError(\n \"Filter and requested wavelength bases must match; implicit air/vacuum conversion is not performed.\"\n );\n }\n if (\n wavelength <\n profile\n .wavelengthRangeNanometers\n .minimum ||\n wavelength >\n profile\n .wavelengthRangeNanometers\n .maximum\n ) {\n throw new InvalidScientificInputError(\n \"Requested wavelength lies outside the filter applicability range.\"\n );\n }\n\n let factor: number;\n let outgoing: LinearStokes;\n const transmission =\n profile.transmission;\n\n if (\n transmission.kind ===\n \"linear-polarizer\"\n ) {\n const k1 = transmission.principalTransmittance.value;\n const k2 = k1 / transmission.extinctionRatio.value;\n outgoing = applyLinearPolarizer(\n incoming,\n k1,\n k2,\n transmission.transmissionAxisDegrees\n );\n factor = outgoing.s0 / incoming.s0;\n } else {\n if (\n transmission.kind ===\n \"neutral-linear-transmission\"\n ) {\n factor =\n transmission\n .linearTransmissionFactor\n .value;\n } else if (\n transmission.kind ===\n \"neutral-optical-density\"\n ) {\n factor =\n Math.pow(\n 10,\n -transmission\n .opticalDensityBase10\n .value\n );\n } else {\n factor =\n interpolateSpectralTransmission(\n transmission.samples.value,\n wavelength\n );\n }\n outgoing = {\n s0: incoming.s0 * factor,\n s1: incoming.s1 * factor,\n s2: incoming.s2 * factor\n };\n }\n\n if (\n !Number.isFinite(factor) ||\n factor <= 0 ||\n factor > 1\n ) {\n throw new InvalidScientificInputError(\n \"Resolved passive filter transmission must remain finite and in (0, 1].\"\n );\n }\n\n const attenuationStops =\n -Math.log2(factor);\n const opticalDensityBase10 =\n -Math.log10(factor);\n\n if (\n !Number.isFinite(\n attenuationStops\n ) ||\n !Number.isFinite(\n opticalDensityBase10\n )\n ) {\n throw new InvalidScientificInputError(\n \"Resolved filter attenuation diagnostics must remain finite.\"\n );\n }\n\n const polarizer = transmission.kind === \"linear-polarizer\";\n return {\n outgoing,\n resolved: {\n schemaVersion:\n profile.schemaVersion,\n filterId:\n profile.filterId,\n profileVersion:\n profile.profileVersion,\n identityScope:\n \"photivra-generic-unbranded\",\n position:\n \"front-of-lens\",\n scientificStatus:\n profile.scientificStatus,\n wavelengthNanometers:\n wavelength,\n wavelengthBasis:\n input.wavelengthBasis,\n transmissionKind:\n transmission.kind,\n linearTransmissionFactor:\n factor,\n attenuationStops,\n opticalDensityBase10,\n polarizationModeled:\n polarizer,\n incidentPolarization:\n stateFromStokes(incoming),\n transmittedPolarization:\n stateFromStokes(outgoing),\n wavelengthChangingBehaviorModeled:\n false,\n lensTransmissionIncluded:\n false,\n sensorOpticalStackIncluded:\n false,\n fieldThroughputIncluded:\n false,\n uncertainty:\n profile.uncertainty,\n evidence: [\n ...profile.evidence,\n ...transmissionEvidence(\n transmission\n )\n ],\n limitations: [\n ...profile.limitations,\n \"Front-of-lens transmission is independent of lens aperture geometry, focus/DOF, diffraction and sensor optical-stack response.\",\n polarizer\n ? \"Linear diattenuator on linear Stokes parameters; circular polarization, retardance, angle-of-incidence dependence and inter-filter reflections/flare/ghosting are not modeled.\"\n : \"Polarization and inter-filter reflections/flare/ghosting are not modeled.\"\n ]\n }\n };\n}\n\n/**\n * Resolves one passive filter at one wavelength. Non-polarizing filters scale all Stokes\n * components equally, so their transmission does not depend on the incident polarization.\n */\nexport function resolveFrontOfLensFilterTransmission(\n input:\n ResolveFrontOfLensFilterTransmissionInput\n): ResolvedFrontOfLensFilterTransmission {\n requireInputKeys(input, \"resolveFrontOfLensFilterTransmission\", [\"profile\", \"wavelengthNanometers\", \"wavelengthBasis\", \"incidentPolarization\"]);\n return resolveComponent(\n input,\n stokesFromState(\n parsePolarizationState(\n input.incidentPolarization,\n \"incidentPolarization\"\n )\n )\n ).resolved;\n}\n\n/**\n * Combines several passive front-of-lens filters at one wavelength, in light-path order, and keeps\n * each filter's identity. Without a polarizer the result is the product of the transmissions. With\n * one, linear Stokes parameters pass through the Mueller matrices in order.\n */\nexport function composeFrontOfLensFilterTransmission(\n input:\n ComposeFrontOfLensFilterTransmissionInput\n): ComposedFrontOfLensFilterTransmission {\n requireInputKeys(input, \"composeFrontOfLensFilterTransmission\", [\"filters\", \"wavelengthNanometers\", \"wavelengthBasis\", \"incidentPolarization\"]);\n if (\n !Array.isArray(\n input.filters\n ) ||\n input.filters.length === 0\n ) {\n throw new InvalidConfigurationError(\n \"filters must be a non-empty array.\"\n );\n }\n\n const incidentPolarization = parsePolarizationState(\n input.incidentPolarization,\n \"incidentPolarization\"\n );\n const incident = stokesFromState(incidentPolarization);\n let stokes = incident;\n const components: ResolvedFrontOfLensFilterTransmission[] = [];\n for (const profile of input.filters) {\n const component = resolveComponent(\n {\n profile,\n wavelengthNanometers:\n input.wavelengthNanometers,\n wavelengthBasis:\n input.wavelengthBasis\n },\n stokes\n );\n components.push(component.resolved);\n stokes = component.outgoing;\n }\n\n const combined = stokes.s0 / incident.s0;\n if (\n !Number.isFinite(combined) ||\n combined <= 0 ||\n combined > 1\n ) {\n throw new InvalidScientificInputError(\n \"Combined passive filter transmission must remain finite and in (0, 1].\"\n );\n }\n\n const stops =\n -Math.log2(combined);\n if (!Number.isFinite(stops)) {\n throw new InvalidScientificInputError(\n \"Combined filter attenuation must remain finite.\"\n );\n }\n\n const polarizationModeled = components.some(\n (component) => component.polarizationModeled\n );\n return {\n schemaVersion: polarizationModeled\n ? FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION\n : FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION,\n wavelengthNanometers:\n scientificWavelength(\n input.wavelengthNanometers\n ),\n wavelengthBasis:\n input.wavelengthBasis,\n appliedFilterCount:\n components.length,\n components,\n combinedLinearTransmissionFactor:\n combined,\n combinedAttenuationStops:\n stops,\n scientificStatus:\n components.some(\n (component) =>\n component\n .scientificStatus ===\n \"approximation\"\n )\n ? \"approximation\"\n : \"calibrated\",\n uncertaintyPropagation:\n \"not-propagated\",\n uncertaintyLimitation:\n \"Component filter uncertainties are preserved individually; aggregate numeric uncertainty is not propagated because independence/correlation is not assumed.\",\n compositionModel: polarizationModeled\n ? \"ordered-linear-stokes-mueller-no-inter-filter-reflections\"\n : \"independent-multiplicative-unpolarized-transmission-no-inter-filter-reflections\",\n polarizationModeled,\n incidentPolarization,\n transmittedPolarization:\n stateFromStokes(stokes),\n wavelengthChangingBehaviorModeled:\n false,\n lensTransmissionIncluded:\n false,\n sensorOpticalStackIncluded:\n false,\n fieldThroughputIncluded:\n false\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"front-of-lens-filter.js","sourceRoot":"","sources":["../../src/optics/front-of-lens-filter.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Generic filters that screw onto the front of the lens.\n *\n * Schema 0.1.0 is explicitly unbranded and unpolarized. It models only passive transmission in front\n * of the lens. It does not cover reflections between stacked filters, flare or ghosting, or filters\n * that change wavelength.\n *\n * Schema 0.2.0 adds one polarizing kind: a linear (partial) polarizer. It has a principal\n * transmittance k1, an extinction ratio k1/k2 and a transmission-axis angle. Polarization is carried\n * as linear Stokes parameters (S0, S1, S2). Filters are applied in order using the Mueller matrix of\n * a linear diattenuator (Gil, arXiv:2002.04105, eqs. 134-135, free; Malus's law: OpenStax University\n * Physics Vol. 3, sec. 1.7, free. Also see: Chipman, Handbook of Optics vol. I ch. 22, 3rd ed., 2010;\n * Goldstein, Polarized Light, 3rd ed., ch. 4-5; Born & Wolf, Principles of Optics, sec. 1.4.2):\n * T = (k1 + k2)/2 + (k1 - k2)/2 * P * cos(2 (psi - theta))\n * Here P is the incident light's degree of linear polarization, psi its polarization angle and theta\n * the filter axis angle.\n * - For P = 1 this is Malus's law: k1 cos^2(psi - theta) + k2 sin^2(psi - theta).\n * - For unpolarized light it is (k1 + k2)/2, about half of k1.\n * Not modelled: circular polarization, retardance (for example the quarter-wave plate in a circular\n * polarizer), dependence on the angle of incidence, and depolarization.\n * @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceBackedFact,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport {\n parseSpectralWavelengthBasis,\n type SpectralWavelengthBasis\n} from \"../core/spectral.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport { requireInputKeys, rejectUnknownFields, rejectUnknownVariantFields, UNCERTAINTY_VARIANT_FIELDS } from \"../core/record-validation.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport const FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION =\n \"0.1.0\" as const;\n/** Schema that also allows the `linear-polarizer` transmission kind. */\nexport const FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION =\n \"0.2.0\" as const;\n\nexport type FrontOfLensFilterProfileSchemaVersion =\n | typeof FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION\n | typeof FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION;\n\n/** Partially linearly polarized light: degree P in [0, 1] and polarization angle psi. */\nexport interface LinearPolarizationState {\n /** Degree of linear polarization P in [0, 1]; 0 is unpolarized. */\n degreeOfLinearPolarization: number;\n /** Electric-field polarization angle, degrees counter-clockwise from image +X. */\n angleDegrees: number;\n}\n\nexport type FrontOfLensFilterScientificStatus =\n | \"calibrated\"\n | \"approximation\";\n\nexport type FrontOfLensFilterUncertainty =\n | {\n kind: \"relative\";\n fraction: number;\n basis: string;\n }\n | {\n kind: \"not-quantified\";\n limitation: string;\n };\n\nexport interface FrontOfLensFilterSpectralSample {\n wavelengthNanometers: number;\n linearTransmissionFactor: number;\n}\n\nexport type FrontOfLensFilterTransmissionModel =\n | {\n kind: \"neutral-linear-transmission\";\n linearTransmissionFactor:\n EvidenceBackedFact<number>;\n }\n | {\n kind: \"neutral-optical-density\";\n opticalDensityBase10:\n EvidenceBackedFact<number>;\n }\n | {\n kind: \"spectral-transmission\";\n samples:\n EvidenceBackedFact<\n readonly FrontOfLensFilterSpectralSample[]\n >;\n }\n | {\n /** Schema 0.2.0 only. Neutral (wavelength-independent) within the declared range. */\n kind: \"linear-polarizer\";\n /** k1: intensity transmittance for light polarized along the transmission axis, (0, 1]. */\n principalTransmittance:\n EvidenceBackedFact<number>;\n /** k1 / k2. Finite and >= 1. Use a large finite ratio for a near-ideal polarizer. */\n extinctionRatio:\n EvidenceBackedFact<number>;\n /** Transmission-axis angle as mounted, degrees counter-clockwise from image +X. */\n transmissionAxisDegrees: number;\n };\n\nexport interface FrontOfLensFilterProfile {\n schemaVersion:\n FrontOfLensFilterProfileSchemaVersion;\n filterId: string;\n profileVersion: string;\n identityScope:\n \"photivra-generic-unbranded\";\n position: \"front-of-lens\";\n scientificStatus:\n FrontOfLensFilterScientificStatus;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n wavelengthRangeNanometers: {\n minimum: number;\n maximum: number;\n };\n transmission:\n FrontOfLensFilterTransmissionModel;\n uncertainty:\n FrontOfLensFilterUncertainty;\n /** True exactly when the transmission kind is `linear-polarizer` (schema 0.2.0). */\n polarizationModeled: boolean;\n wavelengthChangingBehaviorModeled:\n false;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface ResolveFrontOfLensFilterTransmissionInput {\n profile: FrontOfLensFilterProfile;\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n /** Incident polarization; omitted means unpolarized. */\n incidentPolarization?: LinearPolarizationState;\n}\n\nexport interface ResolvedFrontOfLensFilterTransmission {\n schemaVersion:\n FrontOfLensFilterProfileSchemaVersion;\n filterId: string;\n profileVersion: string;\n identityScope:\n \"photivra-generic-unbranded\";\n position: \"front-of-lens\";\n scientificStatus:\n FrontOfLensFilterScientificStatus;\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n transmissionKind:\n FrontOfLensFilterTransmissionModel[\"kind\"];\n /** Intensity transmittance for the declared incident polarization. */\n linearTransmissionFactor: number;\n attenuationStops: number;\n opticalDensityBase10: number;\n polarizationModeled: boolean;\n incidentPolarization: LinearPolarizationState;\n transmittedPolarization: LinearPolarizationState;\n wavelengthChangingBehaviorModeled:\n false;\n lensTransmissionIncluded: false;\n sensorOpticalStackIncluded: false;\n fieldThroughputIncluded: false;\n uncertainty:\n FrontOfLensFilterUncertainty;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface ComposeFrontOfLensFilterTransmissionInput {\n /** Filters in light-path order (scene side first). */\n filters:\n readonly FrontOfLensFilterProfile[];\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n /** Incident scene polarization; omitted means unpolarized. */\n incidentPolarization?: LinearPolarizationState;\n}\n\nexport interface ComposedFrontOfLensFilterTransmission {\n schemaVersion:\n FrontOfLensFilterProfileSchemaVersion;\n wavelengthNanometers: number;\n wavelengthBasis:\n Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n >;\n appliedFilterCount: number;\n components:\n readonly ResolvedFrontOfLensFilterTransmission[];\n combinedLinearTransmissionFactor:\n number;\n combinedAttenuationStops: number;\n scientificStatus:\n FrontOfLensFilterScientificStatus;\n uncertaintyPropagation:\n \"not-propagated\";\n uncertaintyLimitation: string;\n compositionModel:\n | \"independent-multiplicative-unpolarized-transmission-no-inter-filter-reflections\"\n | \"ordered-linear-stokes-mueller-no-inter-filter-reflections\";\n polarizationModeled: boolean;\n incidentPolarization: LinearPolarizationState;\n transmittedPolarization: LinearPolarizationState;\n wavelengthChangingBehaviorModeled:\n false;\n lensTransmissionIncluded: false;\n sensorOpticalStackIncluded: false;\n fieldThroughputIncluded: false;\n}\n\nfunction requireRecord(\n value: unknown,\n path: string,\n allowedKeys: readonly string[] | null\n): UnknownRecord {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be an object.\"\n );\n }\n if (allowedKeys !== null) rejectUnknownFields(value, allowedKeys, path);\n return value as UnknownRecord;\n}\n\nfunction requireNonEmptyString(\n value: unknown,\n path: string\n): string {\n if (\n typeof value !== \"string\" ||\n value.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n path + \" must be a non-empty string.\"\n );\n }\n return value.trim();\n}\n\nfunction requireFinite(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be finite.\"\n );\n }\n return value;\n}\n\nfunction requirePositiveFinite(\n value: unknown,\n path: string\n): number {\n const parsed = requireFinite(\n value,\n path\n );\n if (parsed <= 0) {\n throw new InvalidConfigurationError(\n path +\n \" must be greater than zero.\"\n );\n }\n return parsed;\n}\n\nfunction requireNonNegativeFinite(\n value: unknown,\n path: string\n): number {\n const parsed = requireFinite(\n value,\n path\n );\n if (parsed < 0) {\n throw new InvalidConfigurationError(\n path +\n \" must be greater than or equal to zero.\"\n );\n }\n return parsed;\n}\n\nfunction requirePassiveTransmission(\n value: unknown,\n path: string\n): number {\n const parsed = requirePositiveFinite(\n value,\n path\n );\n if (parsed > 1) {\n throw new InvalidConfigurationError(\n path +\n \" must be less than or equal to one for a passive filter.\"\n );\n }\n return parsed;\n}\n\nfunction parseRange(\n value: unknown,\n path: string\n): {\n minimum: number;\n maximum: number;\n} {\n const record = requireRecord(\n value,\n path, [\"minimum\", \"maximum\"]\n );\n const minimum =\n requirePositiveFinite(\n record.minimum,\n path + \".minimum\"\n );\n const maximum =\n requirePositiveFinite(\n record.maximum,\n path + \".maximum\"\n );\n if (minimum > maximum) {\n throw new InvalidConfigurationError(\n path +\n \".minimum must be less than or equal to maximum.\"\n );\n }\n return {\n minimum,\n maximum\n };\n}\n\nfunction parseResolvedBasis(\n value: unknown,\n path: string\n): Exclude<\n SpectralWavelengthBasis,\n \"unspecified\"\n> {\n const parsed =\n parseSpectralWavelengthBasis(\n value,\n path\n );\n if (parsed === \"unspecified\") {\n throw new InvalidConfigurationError(\n path +\n ' must resolve to \"air\" or \"vacuum\".'\n );\n }\n return parsed;\n}\n\nfunction parseScientificStatus(\n value: unknown,\n path: string\n): FrontOfLensFilterScientificStatus {\n if (\n value !== \"calibrated\" &&\n value !== \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value;\n}\n\nfunction parseUncertainty(\n value: unknown,\n path: string\n): FrontOfLensFilterUncertainty {\n const record = requireRecord(\n value,\n path, null\n );\n rejectUnknownVariantFields(record, \"kind\", UNCERTAINTY_VARIANT_FIELDS, path);\n\n if (record.kind === \"relative\") {\n const fraction =\n requireNonNegativeFinite(\n record.fraction,\n path + \".fraction\"\n );\n if (fraction > 1) {\n throw new InvalidConfigurationError(\n path +\n \".fraction must be less than or equal to one.\"\n );\n }\n return {\n kind: \"relative\",\n fraction,\n basis:\n requireNonEmptyString(\n record.basis,\n path + \".basis\"\n )\n };\n }\n\n if (\n record.kind ===\n \"not-quantified\"\n ) {\n return {\n kind: \"not-quantified\",\n limitation:\n requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseLimitations(\n value: unknown,\n path: string\n): readonly string[] {\n if (!Array.isArray(value)) {\n throw new InvalidConfigurationError(\n path + \" must be an array.\"\n );\n }\n const parsed = value.map(\n (entry, index) =>\n requireNonEmptyString(\n entry,\n path +\n \"[\" +\n index +\n \"]\"\n )\n );\n if (\n new Set(parsed).size !==\n parsed.length\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must not contain duplicates.\"\n );\n }\n return parsed;\n}\n\nfunction parseReusableNumericEvidence(\n value: unknown,\n path: string\n): readonly EvidenceProvenance[] {\n const evidence =\n parseEvidenceList(\n value,\n path\n );\n if (\n evidence.some(\n (entry) =>\n entry.reuseStatus ===\n \"factual-reference-only\"\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \" for embedded numeric filter data must be reusable-data or photivra-owned.\"\n );\n }\n return evidence;\n}\n\nfunction parseSpectralSamples(\n value: unknown,\n path: string\n): readonly FrontOfLensFilterSpectralSample[] {\n if (\n !Array.isArray(value) ||\n value.length < 2\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must contain at least two samples.\"\n );\n }\n\n let previous =\n Number.NEGATIVE_INFINITY;\n return value.map(\n (entry, index) => {\n const samplePath =\n path +\n \"[\" +\n index +\n \"]\";\n const record =\n requireRecord(\n entry,\n samplePath, [\"wavelengthNanometers\", \"linearTransmissionFactor\"]\n );\n const wavelengthNanometers =\n requirePositiveFinite(\n record.wavelengthNanometers,\n samplePath +\n \".wavelengthNanometers\"\n );\n if (\n wavelengthNanometers <=\n previous\n ) {\n throw new InvalidConfigurationError(\n path +\n \" wavelengths must be strictly increasing.\"\n );\n }\n previous =\n wavelengthNanometers;\n return {\n wavelengthNanometers,\n linearTransmissionFactor:\n requirePassiveTransmission(\n record.linearTransmissionFactor,\n samplePath +\n \".linearTransmissionFactor\"\n )\n };\n }\n );\n}\n\nfunction parseTransmission(\n value: unknown,\n path: string,\n polarizerAllowed: boolean\n): FrontOfLensFilterTransmissionModel {\n const record = requireRecord(\n value,\n path, null\n );\n rejectUnknownVariantFields(record, \"kind\", {\n \"neutral-linear-transmission\": [\"kind\", \"linearTransmissionFactor\"],\n \"neutral-optical-density\": [\"kind\", \"opticalDensityBase10\"],\n \"spectral-transmission\": [\"kind\", \"samples\"],\n \"linear-polarizer\": [\"kind\", \"principalTransmittance\", \"extinctionRatio\", \"transmissionAxisDegrees\"]\n }, path);\n\n if (record.kind === \"linear-polarizer\") {\n if (!polarizerAllowed) {\n throw new InvalidConfigurationError(\n path + '.kind \"linear-polarizer\" requires schemaVersion \"' +\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION + '\".'\n );\n }\n const principal = requireRecord(\n record.principalTransmittance,\n path + \".principalTransmittance\", [\"value\", \"evidence\"]\n );\n const extinction = requireRecord(\n record.extinctionRatio,\n path + \".extinctionRatio\", [\"value\", \"evidence\"]\n );\n const ratio = requireFinite(\n extinction.value,\n path + \".extinctionRatio.value\"\n );\n if (ratio < 1) {\n throw new InvalidConfigurationError(\n path + \".extinctionRatio.value must be at least one.\"\n );\n }\n return {\n kind: \"linear-polarizer\",\n principalTransmittance: {\n value: requirePassiveTransmission(\n principal.value,\n path + \".principalTransmittance.value\"\n ),\n evidence: parseEvidenceList(\n principal.evidence,\n path + \".principalTransmittance.evidence\"\n )\n },\n extinctionRatio: {\n value: ratio,\n evidence: parseEvidenceList(\n extinction.evidence,\n path + \".extinctionRatio.evidence\"\n )\n },\n transmissionAxisDegrees: requireFinite(\n record.transmissionAxisDegrees,\n path + \".transmissionAxisDegrees\"\n )\n };\n }\n\n if (\n record.kind ===\n \"neutral-linear-transmission\"\n ) {\n const fact = requireRecord(\n record.linearTransmissionFactor,\n path +\n \".linearTransmissionFactor\", [\"value\", \"evidence\"]\n );\n return {\n kind:\n \"neutral-linear-transmission\",\n linearTransmissionFactor: {\n value:\n requirePassiveTransmission(\n fact.value,\n path +\n \".linearTransmissionFactor.value\"\n ),\n evidence:\n parseEvidenceList(\n fact.evidence,\n path +\n \".linearTransmissionFactor.evidence\"\n )\n }\n };\n }\n\n if (\n record.kind ===\n \"neutral-optical-density\"\n ) {\n const fact = requireRecord(\n record.opticalDensityBase10,\n path +\n \".opticalDensityBase10\", [\"value\", \"evidence\"]\n );\n return {\n kind:\n \"neutral-optical-density\",\n opticalDensityBase10: {\n value:\n requireNonNegativeFinite(\n fact.value,\n path +\n \".opticalDensityBase10.value\"\n ),\n evidence:\n parseEvidenceList(\n fact.evidence,\n path +\n \".opticalDensityBase10.evidence\"\n )\n }\n };\n }\n\n if (\n record.kind ===\n \"spectral-transmission\"\n ) {\n const fact = requireRecord(\n record.samples,\n path + \".samples\", [\"value\", \"evidence\"]\n );\n return {\n kind:\n \"spectral-transmission\",\n samples: {\n value:\n parseSpectralSamples(\n fact.value,\n path +\n \".samples.value\"\n ),\n evidence:\n parseReusableNumericEvidence(\n fact.evidence,\n path +\n \".samples.evidence\"\n )\n }\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\n/**\n * Parses one generic front-of-lens transmission filter.\n *\n * Schema 0.1.0 is explicitly unbranded and unpolarized. It models only\n * passive transmission in front of the lens. It does not cover reflections\n * between stacked filters, polarization, flare or ghosting, or filters that\n * change wavelength.\n */\nexport function parseFrontOfLensFilterProfile(\n value: unknown\n): FrontOfLensFilterProfile {\n const record = requireRecord(\n value,\n \"frontOfLensFilterProfile\", [\"schemaVersion\", \"identityScope\", \"position\", \"wavelengthChangingBehaviorModeled\", \"polarizationModeled\", \"scientificStatus\", \"uncertainty\", \"wavelengthRangeNanometers\", \"transmission\", \"filterId\", \"profileVersion\", \"wavelengthBasis\", \"evidence\", \"limitations\"]\n );\n\n if (\n record.schemaVersion !==\n FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION &&\n record.schemaVersion !==\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'frontOfLensFilterProfile.schemaVersion must be \"' +\n FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION +\n '\" or \"' +\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n const schemaVersion =\n record.schemaVersion as FrontOfLensFilterProfileSchemaVersion;\n if (\n record.identityScope !==\n \"photivra-generic-unbranded\"\n ) {\n throw new InvalidConfigurationError(\n 'frontOfLensFilterProfile.identityScope must be \"photivra-generic-unbranded\".'\n );\n }\n if (\n record.position !==\n \"front-of-lens\"\n ) {\n throw new InvalidConfigurationError(\n 'frontOfLensFilterProfile.position must be \"front-of-lens\".'\n );\n }\n if (\n record.wavelengthChangingBehaviorModeled !==\n false ||\n (schemaVersion ===\n FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION &&\n record.polarizationModeled !== false)\n ) {\n throw new InvalidConfigurationError(\n \"frontOfLensFilterProfile must explicitly keep polarization and wavelength-changing behavior unmodeled in schema 0.1.0.\"\n );\n }\n\n const status =\n parseScientificStatus(\n record.scientificStatus,\n \"frontOfLensFilterProfile.scientificStatus\"\n );\n const uncertainty =\n parseUncertainty(\n record.uncertainty,\n \"frontOfLensFilterProfile.uncertainty\"\n );\n\n if (\n status === \"calibrated\" &&\n uncertainty.kind !==\n \"relative\"\n ) {\n throw new InvalidConfigurationError(\n \"A calibrated filter profile requires quantified relative uncertainty.\"\n );\n }\n\n const range =\n parseRange(\n record.wavelengthRangeNanometers,\n \"frontOfLensFilterProfile.wavelengthRangeNanometers\"\n );\n const transmission =\n parseTransmission(\n record.transmission,\n \"frontOfLensFilterProfile.transmission\",\n schemaVersion ===\n FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION\n );\n const polarizationModeled =\n transmission.kind === \"linear-polarizer\";\n if (record.polarizationModeled !== polarizationModeled) {\n throw new InvalidConfigurationError(\n \"frontOfLensFilterProfile.polarizationModeled must be true exactly for a linear-polarizer transmission.\"\n );\n }\n\n if (\n transmission.kind ===\n \"spectral-transmission\"\n ) {\n const samples =\n transmission.samples.value;\n if (\n samples[0]!\n .wavelengthNanometers >\n range.minimum ||\n samples[\n samples.length - 1\n ]!.wavelengthNanometers <\n range.maximum\n ) {\n throw new InvalidConfigurationError(\n \"Spectral filter samples must cover the declared wavelength range.\"\n );\n }\n }\n\n return {\n schemaVersion,\n filterId:\n requireNonEmptyString(\n record.filterId,\n \"frontOfLensFilterProfile.filterId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"frontOfLensFilterProfile.profileVersion\"\n ),\n identityScope:\n \"photivra-generic-unbranded\",\n position:\n \"front-of-lens\",\n scientificStatus:\n status,\n wavelengthBasis:\n parseResolvedBasis(\n record.wavelengthBasis,\n \"frontOfLensFilterProfile.wavelengthBasis\"\n ),\n wavelengthRangeNanometers:\n range,\n transmission,\n uncertainty,\n polarizationModeled,\n wavelengthChangingBehaviorModeled:\n false,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"frontOfLensFilterProfile.evidence\"\n ),\n limitations:\n parseLimitations(\n record.limitations,\n \"frontOfLensFilterProfile.limitations\"\n )\n };\n}\n\nfunction interpolateSpectralTransmission(\n samples:\n readonly FrontOfLensFilterSpectralSample[],\n wavelengthNanometers: number\n): number {\n const first =\n samples[0]!;\n const last =\n samples[\n samples.length - 1\n ]!;\n\n if (\n wavelengthNanometers ===\n first.wavelengthNanometers\n ) {\n return first\n .linearTransmissionFactor;\n }\n\n for (\n let index = 1;\n index < samples.length;\n index += 1\n ) {\n const right =\n samples[index]!;\n if (\n wavelengthNanometers <=\n right.wavelengthNanometers\n ) {\n const left =\n samples[\n index - 1\n ]!;\n if (\n wavelengthNanometers ===\n right.wavelengthNanometers\n ) {\n return right\n .linearTransmissionFactor;\n }\n const phase =\n (wavelengthNanometers -\n left.wavelengthNanometers) /\n (right.wavelengthNanometers -\n left.wavelengthNanometers);\n return (\n left\n .linearTransmissionFactor +\n phase *\n (right\n .linearTransmissionFactor -\n left\n .linearTransmissionFactor)\n );\n }\n }\n\n return last\n .linearTransmissionFactor;\n}\n\nfunction scientificWavelength(\n value: number\n): number {\n if (\n !Number.isFinite(value) ||\n value <= 0\n ) {\n throw new InvalidScientificInputError(\n \"wavelengthNanometers must be finite and greater than zero.\"\n );\n }\n return value;\n}\n\nfunction transmissionEvidence(\n transmission:\n FrontOfLensFilterTransmissionModel\n): readonly EvidenceProvenance[] {\n if (\n transmission.kind ===\n \"neutral-linear-transmission\"\n ) {\n return transmission\n .linearTransmissionFactor\n .evidence;\n }\n if (\n transmission.kind ===\n \"neutral-optical-density\"\n ) {\n return transmission\n .opticalDensityBase10\n .evidence;\n }\n if (transmission.kind === \"linear-polarizer\") {\n return [\n ...transmission.principalTransmittance.evidence,\n ...transmission.extinctionRatio.evidence\n ];\n }\n return transmission\n .samples.evidence;\n}\n\n/** Linear Stokes vector (S0, S1, S2); circular S3 is not modeled. */\ninterface LinearStokes {\n s0: number;\n s1: number;\n s2: number;\n}\n\nconst UNPOLARIZED: LinearPolarizationState = /* @__PURE__ */ Object.freeze({\n degreeOfLinearPolarization: 0,\n angleDegrees: 0\n});\n\nfunction parsePolarizationState(\n value: LinearPolarizationState | undefined,\n path: string\n): LinearPolarizationState {\n if (value === undefined) {\n return { ...UNPOLARIZED };\n }\n if (typeof value !== \"object\" || value === null) {\n throw new InvalidConfigurationError(path + \" must be an object.\");\n }\n const degree = value.degreeOfLinearPolarization;\n const angle = value.angleDegrees;\n if (\n typeof degree !== \"number\" ||\n !Number.isFinite(degree) ||\n degree < 0 ||\n degree > 1\n ) {\n throw new InvalidScientificInputError(\n path + \".degreeOfLinearPolarization must lie in [0, 1].\"\n );\n }\n if (typeof angle !== \"number\" || !Number.isFinite(angle)) {\n throw new InvalidScientificInputError(\n path + \".angleDegrees must be finite.\"\n );\n }\n return { degreeOfLinearPolarization: degree, angleDegrees: angle };\n}\n\nfunction stokesFromState(state: LinearPolarizationState): LinearStokes {\n const twice = (2 * state.angleDegrees * Math.PI) / 180;\n return {\n s0: 1,\n s1: state.degreeOfLinearPolarization * Math.cos(twice),\n s2: state.degreeOfLinearPolarization * Math.sin(twice)\n };\n}\n\nfunction stateFromStokes(stokes: LinearStokes): LinearPolarizationState {\n const polarized = Math.hypot(stokes.s1, stokes.s2);\n const degree = Math.min(1, polarized / stokes.s0);\n if (degree === 0) {\n return { ...UNPOLARIZED };\n }\n let angle = (Math.atan2(stokes.s2, stokes.s1) * 90) / Math.PI;\n if (angle < 0) angle += 180;\n return { degreeOfLinearPolarization: degree, angleDegrees: angle };\n}\n\n/**\n * Mueller matrix of a linear diattenuator (principal intensity transmittances k1 along the axis\n * and k2 across it, axis at theta) applied to a linear Stokes vector.\n */\nfunction applyLinearPolarizer(\n stokes: LinearStokes,\n k1: number,\n k2: number,\n axisDegrees: number\n): LinearStokes {\n const twice = (2 * axisDegrees * Math.PI) / 180;\n const c = Math.cos(twice);\n const sn = Math.sin(twice);\n const sum = (k1 + k2) / 2;\n const difference = (k1 - k2) / 2;\n const geometric = Math.sqrt(k1 * k2);\n return {\n s0: sum * stokes.s0 + difference * (c * stokes.s1 + sn * stokes.s2),\n s1:\n difference * c * stokes.s0 +\n (sum * c * c + geometric * sn * sn) * stokes.s1 +\n (sum - geometric) * c * sn * stokes.s2,\n s2:\n difference * sn * stokes.s0 +\n (sum - geometric) * c * sn * stokes.s1 +\n (sum * sn * sn + geometric * c * c) * stokes.s2\n };\n}\n\ninterface ResolvedComponent {\n resolved: ResolvedFrontOfLensFilterTransmission;\n outgoing: LinearStokes;\n}\n\nfunction resolveComponent(\n input: ResolveFrontOfLensFilterTransmissionInput,\n incoming: LinearStokes\n): ResolvedComponent {\n const profile =\n parseFrontOfLensFilterProfile(\n input.profile\n );\n const wavelength =\n scientificWavelength(\n input.wavelengthNanometers\n );\n\n if (\n input.wavelengthBasis !==\n profile.wavelengthBasis\n ) {\n throw new InvalidScientificInputError(\n \"Filter and requested wavelength bases must match; implicit air/vacuum conversion is not performed.\"\n );\n }\n if (\n wavelength <\n profile\n .wavelengthRangeNanometers\n .minimum ||\n wavelength >\n profile\n .wavelengthRangeNanometers\n .maximum\n ) {\n throw new InvalidScientificInputError(\n \"Requested wavelength lies outside the filter applicability range.\"\n );\n }\n\n let factor: number;\n let outgoing: LinearStokes;\n const transmission =\n profile.transmission;\n\n if (\n transmission.kind ===\n \"linear-polarizer\"\n ) {\n const k1 = transmission.principalTransmittance.value;\n const k2 = k1 / transmission.extinctionRatio.value;\n outgoing = applyLinearPolarizer(\n incoming,\n k1,\n k2,\n transmission.transmissionAxisDegrees\n );\n factor = outgoing.s0 / incoming.s0;\n } else {\n if (\n transmission.kind ===\n \"neutral-linear-transmission\"\n ) {\n factor =\n transmission\n .linearTransmissionFactor\n .value;\n } else if (\n transmission.kind ===\n \"neutral-optical-density\"\n ) {\n factor =\n Math.pow(\n 10,\n -transmission\n .opticalDensityBase10\n .value\n );\n } else {\n factor =\n interpolateSpectralTransmission(\n transmission.samples.value,\n wavelength\n );\n }\n outgoing = {\n s0: incoming.s0 * factor,\n s1: incoming.s1 * factor,\n s2: incoming.s2 * factor\n };\n }\n\n if (\n !Number.isFinite(factor) ||\n factor <= 0 ||\n factor > 1\n ) {\n throw new InvalidScientificInputError(\n \"Resolved passive filter transmission must remain finite and in (0, 1].\"\n );\n }\n\n const attenuationStops =\n -Math.log2(factor);\n const opticalDensityBase10 =\n -Math.log10(factor);\n\n if (\n !Number.isFinite(\n attenuationStops\n ) ||\n !Number.isFinite(\n opticalDensityBase10\n )\n ) {\n throw new InvalidScientificInputError(\n \"Resolved filter attenuation diagnostics must remain finite.\"\n );\n }\n\n const polarizer = transmission.kind === \"linear-polarizer\";\n return {\n outgoing,\n resolved: {\n schemaVersion:\n profile.schemaVersion,\n filterId:\n profile.filterId,\n profileVersion:\n profile.profileVersion,\n identityScope:\n \"photivra-generic-unbranded\",\n position:\n \"front-of-lens\",\n scientificStatus:\n profile.scientificStatus,\n wavelengthNanometers:\n wavelength,\n wavelengthBasis:\n input.wavelengthBasis,\n transmissionKind:\n transmission.kind,\n linearTransmissionFactor:\n factor,\n attenuationStops,\n opticalDensityBase10,\n polarizationModeled:\n polarizer,\n incidentPolarization:\n stateFromStokes(incoming),\n transmittedPolarization:\n stateFromStokes(outgoing),\n wavelengthChangingBehaviorModeled:\n false,\n lensTransmissionIncluded:\n false,\n sensorOpticalStackIncluded:\n false,\n fieldThroughputIncluded:\n false,\n uncertainty:\n profile.uncertainty,\n evidence: [\n ...profile.evidence,\n ...transmissionEvidence(\n transmission\n )\n ],\n limitations: [\n ...profile.limitations,\n \"Front-of-lens transmission is independent of lens aperture geometry, focus/DOF, diffraction and sensor optical-stack response.\",\n polarizer\n ? \"Linear diattenuator on linear Stokes parameters; circular polarization, retardance, angle-of-incidence dependence and inter-filter reflections/flare/ghosting are not modeled.\"\n : \"Polarization and inter-filter reflections/flare/ghosting are not modeled.\"\n ]\n }\n };\n}\n\n/**\n * Resolves one passive filter at one wavelength. Non-polarizing filters scale all Stokes\n * components equally, so their transmission does not depend on the incident polarization.\n */\nexport function resolveFrontOfLensFilterTransmission(\n input:\n ResolveFrontOfLensFilterTransmissionInput\n): ResolvedFrontOfLensFilterTransmission {\n requireInputKeys(input, \"resolveFrontOfLensFilterTransmission\", [\"profile\", \"wavelengthNanometers\", \"wavelengthBasis\", \"incidentPolarization\"]);\n return resolveComponent(\n input,\n stokesFromState(\n parsePolarizationState(\n input.incidentPolarization,\n \"incidentPolarization\"\n )\n )\n ).resolved;\n}\n\n/**\n * Combines several passive front-of-lens filters at one wavelength, in light-path order, and keeps\n * each filter's identity. Without a polarizer the result is the product of the transmissions. With\n * one, linear Stokes parameters pass through the Mueller matrices in order.\n */\nexport function composeFrontOfLensFilterTransmission(\n input:\n ComposeFrontOfLensFilterTransmissionInput\n): ComposedFrontOfLensFilterTransmission {\n requireInputKeys(input, \"composeFrontOfLensFilterTransmission\", [\"filters\", \"wavelengthNanometers\", \"wavelengthBasis\", \"incidentPolarization\"]);\n if (\n !Array.isArray(\n input.filters\n ) ||\n input.filters.length === 0\n ) {\n throw new InvalidConfigurationError(\n \"filters must be a non-empty array.\"\n );\n }\n\n const incidentPolarization = parsePolarizationState(\n input.incidentPolarization,\n \"incidentPolarization\"\n );\n const incident = stokesFromState(incidentPolarization);\n let stokes = incident;\n const components: ResolvedFrontOfLensFilterTransmission[] = [];\n for (const profile of input.filters) {\n const component = resolveComponent(\n {\n profile,\n wavelengthNanometers:\n input.wavelengthNanometers,\n wavelengthBasis:\n input.wavelengthBasis\n },\n stokes\n );\n components.push(component.resolved);\n stokes = component.outgoing;\n }\n\n const combined = stokes.s0 / incident.s0;\n if (\n !Number.isFinite(combined) ||\n combined <= 0 ||\n combined > 1\n ) {\n throw new InvalidScientificInputError(\n \"Combined passive filter transmission must remain finite and in (0, 1].\"\n );\n }\n\n const stops =\n -Math.log2(combined);\n if (!Number.isFinite(stops)) {\n throw new InvalidScientificInputError(\n \"Combined filter attenuation must remain finite.\"\n );\n }\n\n const polarizationModeled = components.some(\n (component) => component.polarizationModeled\n );\n return {\n schemaVersion: polarizationModeled\n ? FRONT_OF_LENS_POLARIZER_PROFILE_SCHEMA_VERSION\n : FRONT_OF_LENS_FILTER_PROFILE_SCHEMA_VERSION,\n wavelengthNanometers:\n scientificWavelength(\n input.wavelengthNanometers\n ),\n wavelengthBasis:\n input.wavelengthBasis,\n appliedFilterCount:\n components.length,\n components,\n combinedLinearTransmissionFactor:\n combined,\n combinedAttenuationStops:\n stops,\n scientificStatus:\n components.some(\n (component) =>\n component\n .scientificStatus ===\n \"approximation\"\n )\n ? \"approximation\"\n : \"calibrated\",\n uncertaintyPropagation:\n \"not-propagated\",\n uncertaintyLimitation:\n \"Component filter uncertainties are preserved individually; aggregate numeric uncertainty is not propagated because independence/correlation is not assumed.\",\n compositionModel: polarizationModeled\n ? \"ordered-linear-stokes-mueller-no-inter-filter-reflections\"\n : \"independent-multiplicative-unpolarized-transmission-no-inter-filter-reflections\",\n polarizationModeled,\n incidentPolarization,\n transmittedPolarization:\n stateFromStokes(stokes),\n wavelengthChangingBehaviorModeled:\n false,\n lensTransmissionIncluded:\n false,\n sensorOpticalStackIncluded:\n false,\n fieldThroughputIncluded:\n false\n };\n}\n"]}
|
|
@@ -31,7 +31,7 @@ import { requireAllowlistedRecord } from "../core/record-validation.js";
|
|
|
31
31
|
import { FULL_RESOLUTION_CEILING_PIXELS, resolveRaisedLimit } from "../core/pixel-limits.js";
|
|
32
32
|
export const IRRADIANCE_CONVOLUTION_SCHEMA_VERSION = "0.1.0";
|
|
33
33
|
/** `maximumPixels` is the default grid limit; a request may raise it with its own `maximumPixels`, up to `ceilingPixels`. */
|
|
34
|
-
export const IRRADIANCE_CONVOLUTION_LIMITS = Object.freeze({
|
|
34
|
+
export const IRRADIANCE_CONVOLUTION_LIMITS = /* @__PURE__ */ Object.freeze({
|
|
35
35
|
maximumPixels: 24_000_000,
|
|
36
36
|
ceilingPixels: FULL_RESOLUTION_CEILING_PIXELS,
|
|
37
37
|
maximumDimension: 16_384,
|