@photivra/engine 2.19.0 → 2.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/CHANGELOG.md +112 -1
  2. package/CITATION.cff +1 -1
  3. package/NODE_SUPPORT.md +7 -5
  4. package/README.md +6 -6
  5. package/SECURITY.md +1 -1
  6. package/THIRD_PARTY.md +14 -10
  7. package/dist/capture/dng-lens-correction-opcodes.d.ts +32 -0
  8. package/dist/capture/dng-lens-correction-opcodes.js +119 -0
  9. package/dist/capture/dng-lens-correction-opcodes.js.map +1 -0
  10. package/dist/capture/native-environment-lean.js +1 -5
  11. package/dist/capture/native-environment-lean.js.map +1 -1
  12. package/dist/capture/native-raw-dng.d.ts +6 -0
  13. package/dist/capture/native-raw-dng.js +16 -2
  14. package/dist/capture/native-raw-dng.js.map +1 -1
  15. package/dist/capture/sensor-raw-producer.js +3 -5
  16. package/dist/capture/sensor-raw-producer.js.map +1 -1
  17. package/dist/core/shared-helpers.d.ts +2 -0
  18. package/dist/core/shared-helpers.js +4 -0
  19. package/dist/core/shared-helpers.js.map +1 -1
  20. package/dist/core/version.d.ts +1 -1
  21. package/dist/core/version.js +1 -1
  22. package/dist/core/version.js.map +1 -1
  23. package/dist/equipment/generic-lens-catalogue.d.ts +8 -2
  24. package/dist/equipment/generic-lens-catalogue.js +31 -2
  25. package/dist/equipment/generic-lens-catalogue.js.map +1 -1
  26. package/dist/equipment/generic-tier-assets.js +2 -3
  27. package/dist/equipment/generic-tier-assets.js.map +1 -1
  28. package/dist/equipment/generic-tier-presets.js +2 -3
  29. package/dist/equipment/generic-tier-presets.js.map +1 -1
  30. package/dist/facade/display-view-gpu.d.ts +7 -4
  31. package/dist/facade/display-view-gpu.js +4 -4
  32. package/dist/facade/display-view-gpu.js.map +1 -1
  33. package/dist/facade/display-view-lens-signal.d.ts +1 -1
  34. package/dist/facade/display-view-lens-signal.js +5 -3
  35. package/dist/facade/display-view-lens-signal.js.map +1 -1
  36. package/dist/facade/display-view.d.ts +3 -1
  37. package/dist/facade/display-view.js +1 -1
  38. package/dist/facade/display-view.js.map +1 -1
  39. package/dist/facade/fast-methods.d.ts +50 -0
  40. package/dist/facade/fast-methods.js +50 -0
  41. package/dist/facade/fast-methods.js.map +1 -0
  42. package/dist/facade/fast-resolution.d.ts +12 -0
  43. package/dist/facade/fast-resolution.js +18 -0
  44. package/dist/facade/fast-resolution.js.map +1 -0
  45. package/dist/facade/generic-lens-capture.d.ts +3 -2
  46. package/dist/facade/generic-lens-capture.js +3 -2
  47. package/dist/facade/generic-lens-capture.js.map +1 -1
  48. package/dist/facade/simulate-capture.d.ts +51 -11
  49. package/dist/facade/simulate-capture.js +144 -75
  50. package/dist/facade/simulate-capture.js.map +1 -1
  51. package/dist/facade/simulate-display-view.d.ts +3 -2
  52. package/dist/facade/simulate-display-view.js +22 -12
  53. package/dist/facade/simulate-display-view.js.map +1 -1
  54. package/dist/index.d.ts +7 -0
  55. package/dist/index.js +5 -0
  56. package/dist/index.js.map +1 -1
  57. package/dist/optics/aperture-diameter.d.ts +47 -0
  58. package/dist/optics/aperture-diameter.js +50 -0
  59. package/dist/optics/aperture-diameter.js.map +1 -0
  60. package/dist/optics/detail-limit.d.ts +182 -0
  61. package/dist/optics/detail-limit.js +336 -0
  62. package/dist/optics/detail-limit.js.map +1 -0
  63. package/dist/optics/generic-lens-psf.d.ts +18 -2
  64. package/dist/optics/generic-lens-psf.js +25 -2
  65. package/dist/optics/generic-lens-psf.js.map +1 -1
  66. package/dist/optics/scene-to-sensor-irradiance.d.ts +13 -0
  67. package/dist/optics/scene-to-sensor-irradiance.js +7 -0
  68. package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
  69. package/dist/output/crop-to-match-focal-length.d.ts +62 -0
  70. package/dist/output/crop-to-match-focal-length.js +63 -0
  71. package/dist/output/crop-to-match-focal-length.js.map +1 -0
  72. package/dist/output/developed-lens-corrections.js +2 -2
  73. package/dist/output/developed-lens-corrections.js.map +1 -1
  74. package/dist/output/generic-lens-corrections.d.ts +3 -1
  75. package/dist/output/generic-lens-corrections.js +8 -4
  76. package/dist/output/generic-lens-corrections.js.map +1 -1
  77. package/dist/output/lens-corrections.d.ts +12 -2
  78. package/dist/output/lens-corrections.js +22 -7
  79. package/dist/output/lens-corrections.js.map +1 -1
  80. package/dist/output/print-contrast-reference.js +1 -1
  81. package/dist/output/print-contrast-reference.js.map +1 -1
  82. package/dist/output/print-size-blur-noise.d.ts +110 -0
  83. package/dist/output/print-size-blur-noise.js +138 -0
  84. package/dist/output/print-size-blur-noise.js.map +1 -0
  85. package/dist/sensor/eqe-electron-rate.js +1 -7
  86. package/dist/sensor/eqe-electron-rate.js.map +1 -1
  87. package/dist/sensor/exposure-window.d.ts +2 -0
  88. package/dist/sensor/exposure-window.js +2 -2
  89. package/dist/sensor/exposure-window.js.map +1 -1
  90. package/dist/sensor/readout-timing.js +2 -23
  91. package/dist/sensor/readout-timing.js.map +1 -1
  92. package/dist/sensor/response-application-compatibility.js +1 -6
  93. package/dist/sensor/response-application-compatibility.js.map +1 -1
  94. package/dist/sensor/responsivity-photocurrent.js +1 -7
  95. package/dist/sensor/responsivity-photocurrent.js.map +1 -1
  96. package/dist/sensor/sensor-characteristics.d.ts +137 -0
  97. package/dist/sensor/sensor-characteristics.js +115 -0
  98. package/dist/sensor/sensor-characteristics.js.map +1 -0
  99. package/dist/sensor/spatial-sample-reduction.js +1 -5
  100. package/dist/sensor/spatial-sample-reduction.js.map +1 -1
  101. package/dist/sensor/spectral-quadrature.js +1 -6
  102. package/dist/sensor/spectral-quadrature.js.map +1 -1
  103. package/dist/sensor/temporal-photo-signal.d.ts +3 -0
  104. package/dist/sensor/temporal-photo-signal.js +5 -2
  105. package/dist/sensor/temporal-photo-signal.js.map +1 -1
  106. package/dist/stabilization/system.d.ts +9 -0
  107. package/dist/stabilization/system.js +5 -6
  108. package/dist/stabilization/system.js.map +1 -1
  109. package/docs/AGENT_GUIDE.md +4 -0
  110. package/docs/API_REFERENCE.md +76 -2
  111. package/docs/QUICK_START.md +88 -6
  112. package/docs/USAGE.md +65 -2
  113. package/docs/api/capture-native-raw-dng.md +6 -0
  114. package/docs/api/core-version.md +1 -1
  115. package/docs/api/equipment-generic-lens-catalogue.md +7 -2
  116. package/docs/api/exports.json +152 -2
  117. package/docs/api/facade-display-view-gpu.md +5 -2
  118. package/docs/api/facade-fast-methods.md +91 -0
  119. package/docs/api/facade-simulate-capture.md +36 -11
  120. package/docs/api/facade-simulate-display-view.md +3 -2
  121. package/docs/api/optics-aperture-diameter.md +51 -0
  122. package/docs/api/optics-detail-limit.md +203 -0
  123. package/docs/api/output-crop-to-match-focal-length.md +67 -0
  124. package/docs/api/output-generic-lens-corrections.md +3 -1
  125. package/docs/api/output-lens-corrections.md +11 -1
  126. package/docs/api/output-print-size-blur-noise.md +115 -0
  127. package/docs/api/sensor-sensor-characteristics.md +105 -0
  128. package/llms.txt +4 -0
  129. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import type { EvidenceProvenance } from "../core/evidence-provenance.js";
2
2
  import { type ResolvedGenericLens } from "../equipment/generic-lens-catalogue.js";
3
3
  import { type LensSampledPsfProfile } from "./lens-psf-profile.js";
4
+ import { type DefocusBokehSiteKernel } from "./defocus-bokeh-kernel.js";
4
5
  /** Wavelength nodes of a catalogue PSF profile, nm (they span the facade's 380–780 nm quadrature). */
5
6
  export declare const GENERIC_LENS_PSF_WAVELENGTHS_NM: readonly [380, 450, 550, 650, 780];
6
7
  /** Largest kernel radius of the aberration PSF in sites (before any defocus disc is convolved in). */
@@ -25,10 +26,11 @@ export interface GenericLensPsfInput {
25
26
  x: number;
26
27
  y: number;
27
28
  };
28
- /** Optional site kernel (2R_d + 1)² to convolve into every node (the `lens.defocus` disc). */
29
+ /** Optional site kernel (2R_d + 1)² to convolve into each node, by its field point (mm, +Y up): the `lens.defocus` bokeh kernel. */
29
30
  extraKernel?: {
30
- weights: Float64Array;
31
31
  radius: number;
32
+ clipped?: boolean;
33
+ at(fieldXmm: number, fieldYmm: number): Float64Array;
32
34
  };
33
35
  evidence: readonly EvidenceProvenance[];
34
36
  }
@@ -66,3 +68,17 @@ export declare function genericLensPsfKernelRadius(input: {
66
68
  * kernel on the site lattice. Engine-owned (parsed once). Deterministic: the same input gives the same profile.
67
69
  */
68
70
  export declare function createGenericLensPsfProfile(input: GenericLensPsfInput): GenericLensPsf;
71
+ /**
72
+ * #567: the catalogue lens's own bokeh kernel for `lens.defocus` (#553's shaped kernel with `lens.character.bokeh`), as the
73
+ * PSF's field-dependent extra kernel. The defocus is referred to the lens's focus, the balanced one of its PSF (W020 = −W040):
74
+ * the ray map (σc/2 + bρ²)·P of the paraxial focus gains −(b/2)·P, so the kernel is #553's for the signed blur σc − b. Rows are
75
+ * flipped from #553's (+Y down) to the profile's (+Y up). With a cat's eye each field point (tangent x/f, y/f: the rectilinear
76
+ * chief ray, distortion neglected) has its own kernel, padded to the axis kernel's radius (clipping only narrows the blur). Each
77
+ * call builds its kernel (the profile calls it once per field and wavelength node: 125 small kernels). `catsEye` false leaves it out.
78
+ */
79
+ export declare function genericLensBokehKernel(lens: ResolvedGenericLens, diameterSites: number, side: 1 | -1, pitch: number, catsEye: boolean): {
80
+ axis: DefocusBokehSiteKernel;
81
+ radius: number;
82
+ clipped: boolean;
83
+ at(fieldXmm: number, fieldYmm: number): Float64Array;
84
+ };
@@ -23,6 +23,7 @@ import { InvalidScientificInputError } from "../core/validation.js";
23
23
  import { genericLensDispersion } from "../equipment/generic-lens-catalogue.js";
24
24
  import { markEngineOwnedLensSampledPsfProfile } from "./lens-psf-profile.js";
25
25
  import { convolveSiteKernels } from "./defocus-disc-kernel.js";
26
+ import { createDefocusBokehSiteKernel } from "./defocus-bokeh-kernel.js";
26
27
  /** Wavelength nodes of a catalogue PSF profile, nm (they span the facade's 380–780 nm quadrature). */
27
28
  export const GENERIC_LENS_PSF_WAVELENGTHS_NM = /* @__PURE__ */ Object.freeze([380, 450, 550, 650, 780]);
28
29
  /** Largest kernel radius of the aberration PSF in sites (before any defocus disc is convolved in). */
@@ -313,7 +314,7 @@ export function createGenericLensPsfProfile(input) {
313
314
  const base = quadrant.get(Math.abs(x) + ":" + Math.abs(y) + ":" + nm);
314
315
  let kernel = mirror(crop(base), radius, x < 0, y < 0);
315
316
  if (extra)
316
- kernel = convolveSiteKernels(kernel, radius, extra.weights, extra.radius);
317
+ kernel = convolveSiteKernels(kernel, radius, extra.at(x, y), extra.radius);
317
318
  nodes.push({ nodeId: "pv-" + x.toFixed(6) + "-" + y.toFixed(6) + "-" + nm,
318
319
  coordinate: { focalLengthMm: f, focusDiopters, apertureFNumber: N, fieldXmm: x, fieldYmm: y, wavelengthNm: nm, signedDefocusImagePlaneMicrometers: 0 },
319
320
  kernel: { widthSamples: w, heightSamples: w, samplePitchMicrometersX: pitch, samplePitchMicrometersY: pitch, centerSampleX: kernelRadius, centerSampleY: kernelRadius,
@@ -323,7 +324,7 @@ export function createGenericLensPsfProfile(input) {
323
324
  const profile = { schemaVersion: "0.1.0", profileId: "photivra-" + lens.lensId + ":psf", profileVersion: "1.0.0", scientificStatus: "approximation",
324
325
  opticalDomain: "lens-primary-optical-path-only", coordinateSystem: "image-plane-metric", fieldAxes: "+X right, +Y up", kernelEnergyNormalization: "unit-energy-shape",
325
326
  interpolation: "bounded-regular-grid-centroid-aligned", throughputOwnership: "separate-relative-pupil-throughput-factor",
326
- responseIncludes: { diffraction: true, aberration: true, defocus: extra !== undefined, pupilClippingShape: false },
327
+ responseIncludes: { diffraction: true, aberration: true, defocus: extra !== undefined, pupilClippingShape: extra?.clipped === true },
327
328
  sensorOpticalStackIncluded: false, sensorSamplingIncluded: false, reconstructionIncluded: false, strayLightIncluded: false,
328
329
  axes: { focalLengthMm: [f], focusDiopters: [focusDiopters], apertureFNumber: [N], fieldXmm: fieldX, fieldYmm: fieldY, wavelengthNm: [...GENERIC_LENS_PSF_WAVELENGTHS_NM],
329
330
  signedDefocusImagePlaneMicrometers: [0] }, nodes, evidence: input.evidence,
@@ -334,4 +335,26 @@ export function createGenericLensPsfProfile(input) {
334
335
  transformSize: { minimum: minimumTransform, maximum: maximumTransform }, maximumPhaseStepWaves: phaseStep, fieldXmm: fieldX, fieldYmm: fieldY,
335
336
  wavelengthsNm: [...GENERIC_LENS_PSF_WAVELENGTHS_NM] };
336
337
  }
338
+ /**
339
+ * #567: the catalogue lens's own bokeh kernel for `lens.defocus` (#553's shaped kernel with `lens.character.bokeh`), as the
340
+ * PSF's field-dependent extra kernel. The defocus is referred to the lens's focus, the balanced one of its PSF (W020 = −W040):
341
+ * the ray map (σc/2 + bρ²)·P of the paraxial focus gains −(b/2)·P, so the kernel is #553's for the signed blur σc − b. Rows are
342
+ * flipped from #553's (+Y down) to the profile's (+Y up). With a cat's eye each field point (tangent x/f, y/f: the rectilinear
343
+ * chief ray, distortion neglected) has its own kernel, padded to the axis kernel's radius (clipping only narrows the blur). Each
344
+ * call builds its kernel (the profile calls it once per field and wavelength node: 125 small kernels). `catsEye` false leaves it out.
345
+ */
346
+ export function genericLensBokehKernel(lens, diameterSites, side, pitch, catsEye) {
347
+ const b = lens.character.bokeh, options = (catsEye ? b : { blades: b.blades, sphericalAberration: b.sphericalAberration }), N = lens.character.fNumber, f = lens.focalLengthMm;
348
+ const s = side * diameterSites - 8 * N * options.sphericalAberration.w040Micrometers / pitch;
349
+ const build = (x, y) => createDefocusBokehSiteKernel({ diameterSites: Math.abs(s), side: s < 0 ? -1 : 1, fNumber: N,
350
+ focalLengthMm: f, pitchMicrometers: pitch, options, field: { x: x / f, y: y / f } });
351
+ const axis = build(0, 0), R = axis.radius, w = 2 * R + 1;
352
+ return { axis, radius: R, clipped: !!options.catsEye, at(x, y) {
353
+ const k = options.catsEye ? build(x, y) : axis, r = k.radius, out = new Float64Array(w * w);
354
+ for (let j = -r; j <= r; j++)
355
+ for (let i = -r; i <= r; i++)
356
+ out[(R - j) * w + i + R] = k.weights[(j + r) * k.width + i + r];
357
+ return out;
358
+ } };
359
+ }
337
360
  //# sourceMappingURL=generic-lens-psf.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"generic-lens-psf.js","sourceRoot":"","sources":["../../src/optics/generic-lens-psf.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * The PSF of a generic catalogue lens (#549) on a sensor's site lattice, as a field- and wavelength-dependent sampled PSF\n * profile for the environment PSF quadrature (`simulateCapture` `lens.catalogue`).\n *\n * Model (an approximation): scalar Fraunhofer diffraction of a uniform circular pupil of diameter D = f/N carrying the\n * lens's Seidel wavefront (`resolveGenericLens`; the expansion of `createWavefrontPupilGrid`, Hopkins 1950; Wyant & Creath\n * 1992), propagated to the thin-lens image distance z (working f-number z/D; Goodman, Introduction to Fourier Optics, ch. 4-6).\n * U(x) = Σ_pupil exp(i·2π·W(u)/λ)·exp(−i·2π·x·u/(λ·z)) is evaluated with a zero-padded radix-2 FFT (Cooley & Tukey 1965) on\n * an image grid of pitch δ = min(λ·N_w/2, p/4) (p the site pitch), and |U|² is integrated over each site's square cell (exact\n * overlap of each δ-square with the cell). Lateral colour displaces the PSF radially by Δr(λ). The kernel window is (2R + 1)²\n * sites; the energy outside it is reported and put back by unit-sum renormalisation, as for `lens.diffraction`.\n *\n * Nodes: a 5 × 5 regular grid of field points (0, ±half the frame, ±the frame edge plus the kernel reach) × 5 wavelengths\n * (380, 450, 550, 650, 780 nm), each computed at its own field azimuth (no rotation of a radial node), interpolated by the\n * engine's centroid-aligned multilinear scheme. The quadrant x, y ≥ 0 is computed and mirrored (the Seidel PSF of a mirrored\n * field point is the mirrored PSF).\n *\n * Kernel orientation: a kernel's row index increases with image +Y, the orientation the environment PSF quadrature applies\n * (`sensorPsfSourcePoint`), so coma and lateral colour point away from the optical axis in the rendered image.\n */\n\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport type { EvidenceProvenance } from \"../core/evidence-provenance.js\";\nimport { genericLensDispersion, type ResolvedGenericLens } from \"../equipment/generic-lens-catalogue.js\";\nimport { markEngineOwnedLensSampledPsfProfile, type LensSampledPsfGridNode, type LensSampledPsfProfile } from \"./lens-psf-profile.js\";\nimport { convolveSiteKernels } from \"./defocus-disc-kernel.js\";\n\n/** Wavelength nodes of a catalogue PSF profile, nm (they span the facade's 380–780 nm quadrature). */\nexport const GENERIC_LENS_PSF_WAVELENGTHS_NM = /* @__PURE__ */ Object.freeze([380, 450, 550, 650, 780] as const);\n/** Largest kernel radius of the aberration PSF in sites (before any defocus disc is convolved in). */\nexport const GENERIC_LENS_PSF_MAXIMUM_KERNEL_RADIUS_SITES = 12;\n/** Largest kernel radius in sites of the catalogue PSF with a defocus disc convolved in (`simulateCapture` refuses more: cost). */\nexport const GENERIC_LENS_PSF_MAXIMUM_COMBINED_RADIUS_SITES = 16;\n/** Energy fraction a node may leave outside the chosen kernel window (it is put back by renormalisation and reported). */\nexport const GENERIC_LENS_PSF_WINDOW_TRUNCATION = 0.03;\n/** Largest FFT size per axis. */\nconst MAXIMUM_TRANSFORM = 2048;\n/** Largest optical-path step between neighbouring pupil samples, in waves (Nyquist is 0.5). */\nconst MAXIMUM_PHASE_STEP_WAVES = 0.35;\nconst DESIGN_WAVELENGTH_UM = 0.55;\n\nexport interface GenericLensPsfInput {\n /** The lens resolved at the capture's f-number and focus distance (`resolveGenericLens`). */\n lens: ResolvedGenericLens;\n /** Finite focus distance, m (the thin-lens image distance sets the propagation distance). */\n focusDistanceM: number;\n sitePitchMicrometers: number;\n /** Half extent of the field the profile must cover, mm (the frame's half width and height plus the PSF and query reach). */\n fieldHalfExtentMm: { x: number; y: number };\n /** The frame's half width and height, mm (the inner field nodes sit at half of them). */\n frameHalfMm: { x: number; y: number };\n /** Optional site kernel (2R_d + 1)² to convolve into every node (the `lens.defocus` disc). */\n extraKernel?: { weights: Float64Array; radius: number };\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface GenericLensPsf {\n profile: LensSampledPsfProfile;\n /** Radius of the aberration PSF window, sites, and of the applied kernel (with `extraKernel`). */\n aberrationKernelRadiusSites: number;\n kernelRadiusSites: number;\n /** Largest energy fraction outside the aberration window over the nodes (put back by renormalisation). */\n maximumTruncatedEnergyFraction: number;\n /** FFT sizes used (smallest, largest) and the largest pupil phase step, waves. */\n transformSize: { minimum: number; maximum: number };\n maximumPhaseStepWaves: number;\n /** Field node coordinates, mm, and wavelengths, nm. */\n fieldXmm: readonly number[];\n fieldYmm: readonly number[];\n wavelengthsNm: readonly number[];\n}\n\n/** In-place iterative radix-2 FFT, exp(−i·2π·k·m/n). */\nfunction radix2Fft(re: Float64Array, im: Float64Array, n: number, cos: Float64Array, sin: Float64Array): void {\n for (let i = 1, j = 0; i < n; i++) {\n let bit = n >> 1;\n for (; j & bit; bit >>= 1) j ^= bit;\n j ^= bit;\n if (i < j) { let t = re[i]!; re[i] = re[j]!; re[j] = t; t = im[i]!; im[i] = im[j]!; im[j] = t; }\n }\n for (let size = 2; size <= n; size <<= 1) {\n const half = size >> 1, step = n / size;\n for (let start = 0; start < n; start += size) for (let k = 0; k < half; k++) {\n const c = cos[k * step]!, s = sin[k * step]!, a = start + k, b = a + half;\n const tr = re[b]! * c + im[b]! * s, ti = im[b]! * c - re[b]! * s;\n re[b] = re[a]! - tr; im[b] = im[a]! - ti; re[a] = re[a]! + tr; im[a] = im[a]! + ti;\n }\n }\n}\n\n/** One axis's overlap of δ-squares centred at positions (s·δ + shift) with site cells [(i − ½)p, (i + ½)p], i ∈ [−R, R]. */\nfunction overlaps(count: number, delta: number, shift: number, pitch: number, radius: number): { cell: Int32Array; weight: Float64Array; cell2: Int32Array; weight2: Float64Array } {\n const cell = new Int32Array(count).fill(-1), weight = new Float64Array(count), cell2 = new Int32Array(count).fill(-1), weight2 = new Float64Array(count);\n for (let k = 0; k < count; k++) {\n const signed = k < count / 2 ? k : k - count, centre = signed * delta + shift, lo = centre - delta / 2, hi = centre + delta / 2;\n const first = Math.floor(lo / pitch + 0.5), last = Math.floor(hi / pitch + 0.5);\n for (let i = first; i <= last && i <= first + 1; i++) {\n if (i < -radius || i > radius) continue;\n const w = (Math.min(hi, (i + 0.5) * pitch) - Math.max(lo, (i - 0.5) * pitch)) / delta;\n if (w <= 0) continue;\n if (cell[k] === -1) { cell[k] = i + radius; weight[k] = w; } else { cell2[k] = i + radius; weight2[k] = w; }\n }\n }\n return { cell, weight, cell2, weight2 };\n}\n\n/** A node's energy per site cell over the (2R₀ + 1)² window (not normalised) and the whole period's energy. */\ninterface NodeResult { kernel: Float64Array; total: number; transform: number; phaseStep: number }\n\n/** Seidel OPD (µm) at normalised pupil (px, py) for a field point at height H and azimuth φ, at wavelength λ (µm). */\nfunction opdMicrometers(lens: ResolvedGenericLens, H: number, cosPhi: number, sinPhi: number, lambdaUm: number, px: number, py: number): number {\n const a = lens.character.aberrations, r2 = px * px + py * py, along = px * cosPhi + py * sinPhi;\n const defocus = a.balancingDefocusWaves + a.axialColorWaves * genericLensDispersion(lambdaUm * 1000);\n // Positive coma W131 sends the comet's flare away from the axis in the image (H ρ³ cos(θ − φ), with the FFT sign above).\n return DESIGN_WAVELENGTH_UM * (defocus * r2 + a.sphericalWaves * r2 * r2 + a.comaWaves * H * r2 * along + a.astigmatismWaves * H * H * along * along + a.fieldCurvatureWaves * H * H * r2);\n}\n\n/** Largest transverse ray aberration 2·N_w·|∂W/∂ρ| (µm) over the pupil, from a 33 × 33 grid. */\nfunction geometricRadiusMicrometers(lens: ResolvedGenericLens, H: number, lambdaUm: number, workingF: number): number {\n let largest = 0;\n const n = 33, h = 1e-4;\n for (let j = 0; j < n; j++) for (let i = 0; i < n; i++) {\n const px = -1 + 2 * i / (n - 1), py = -1 + 2 * j / (n - 1);\n if (px * px + py * py > 1) continue;\n const gx = (opdMicrometers(lens, H, 1, 0, lambdaUm, px + h, py) - opdMicrometers(lens, H, 1, 0, lambdaUm, px - h, py)) / (2 * h);\n const gy = (opdMicrometers(lens, H, 1, 0, lambdaUm, px, py + h) - opdMicrometers(lens, H, 1, 0, lambdaUm, px, py - h)) / (2 * h);\n largest = Math.max(largest, Math.hypot(gx, gy));\n }\n return 2 * workingF * largest;\n}\n\nfunction nodeKernel(lens: ResolvedGenericLens, xMm: number, yMm: number, lambdaNm: number, workingF: number, pupilDiameterMm: number, zMm: number,\n pitch: number, radius: number): NodeResult {\n const lambdaUm = lambdaNm / 1000, r = Math.hypot(xMm, yMm), H = Math.min(1, r / lens.halfDiagonalMm);\n const cosPhi = r > 0 ? xMm / r : 1, sinPhi = r > 0 ? yMm / r : 0;\n // Lateral colour: radial displacement L·R·H·D(λ), µm.\n const shift = lens.character.lateralColor.fraction * lens.halfDiagonalMm * 1000 * H * genericLensDispersion(lambdaNm);\n const delta = Math.min(lambdaUm * workingF / 2, pitch / 4);\n let size = 64;\n // The FFT period must hold the window, or (when the PSF is much smaller than the window, for large pixels) the PSF itself:\n // the geometric blur plus 16·λ·N_w of Airy rings (the energy beyond, about 1 %, folds back into the period).\n const psfExtentUm = 2 * (geometricRadiusMicrometers(lens, H, lambdaUm, workingF) + 16 * lambdaUm * workingF);\n while (size * delta < Math.min(2.5 * (radius + 0.5) * pitch, psfExtentUm) + 2 * Math.abs(shift)) size *= 2;\n for (;;) {\n if (size > MAXIMUM_TRANSFORM) throw new InvalidScientificInputError(\"The catalogue lens PSF needs an FFT larger than \" + MAXIMUM_TRANSFORM + \" per axis.\");\n // Pupil pitch: δ · p_pupil = λ·z / size (mm).\n const pupilPitchMm = lambdaUm / 1000 * zMm / (size * delta / 1000), half = pupilDiameterMm / 2, reach = Math.floor(half / pupilPitchMm);\n const re = new Float64Array(size * size), im = new Float64Array(size * size), rowUsed = new Uint8Array(size);\n let open = 0, phaseStep = 0;\n const opd = new Float64Array((2 * reach + 1) * (2 * reach + 1)).fill(NaN);\n for (let v = -reach; v <= reach; v++) for (let u = -reach; u <= reach; u++) {\n const px = u * pupilPitchMm / half, py = v * pupilPitchMm / half;\n if (px * px + py * py > 1 + 1e-12) continue;\n const w = opdMicrometers(lens, H, cosPhi, sinPhi, lambdaUm, px, py), phase = 2 * Math.PI * w / lambdaUm;\n opd[(v + reach) * (2 * reach + 1) + u + reach] = w;\n const index = ((v + size) % size) * size + (u + size) % size;\n re[index] = Math.cos(phase); im[index] = Math.sin(phase); rowUsed[(v + size) % size] = 1; open++;\n }\n const width = 2 * reach + 1;\n for (let j = 0; j < width; j++) for (let i = 0; i < width; i++) {\n const w = opd[j * width + i]!;\n if (Number.isNaN(w)) continue;\n if (i + 1 < width && !Number.isNaN(opd[j * width + i + 1]!)) phaseStep = Math.max(phaseStep, Math.abs(opd[j * width + i + 1]! - w) / lambdaUm);\n if (j + 1 < width && !Number.isNaN(opd[(j + 1) * width + i]!)) phaseStep = Math.max(phaseStep, Math.abs(opd[(j + 1) * width + i]! - w) / lambdaUm);\n }\n if (open < 9) throw new InvalidScientificInputError(\"The catalogue lens PSF pupil has fewer than 9 samples.\");\n if (phaseStep > MAXIMUM_PHASE_STEP_WAVES) { size *= 2; continue; }\n const cos = new Float64Array(size / 2), sin = new Float64Array(size / 2);\n for (let k = 0; k < size / 2; k++) { cos[k] = Math.cos(2 * Math.PI * k / size); sin[k] = Math.sin(2 * Math.PI * k / size); }\n const rowRe = new Float64Array(size), rowIm = new Float64Array(size);\n for (let y = 0; y < size; y++) {\n if (!rowUsed[y]) continue;\n rowRe.set(re.subarray(y * size, (y + 1) * size)); rowIm.set(im.subarray(y * size, (y + 1) * size));\n radix2Fft(rowRe, rowIm, size, cos, sin);\n re.set(rowRe, y * size); im.set(rowIm, y * size);\n }\n const colRe = new Float64Array(size), colIm = new Float64Array(size);\n const ox = overlaps(size, delta, shift * cosPhi, pitch, radius), oy = overlaps(size, delta, shift * sinPhi, pitch, radius);\n const w2 = 2 * radius + 1, kernel = new Float64Array(w2 * w2);\n let total = 0, inside = 0;\n for (let x = 0; x < size; x++) {\n for (let y = 0; y < size; y++) { colRe[y] = re[y * size + x]!; colIm[y] = im[y * size + x]!; }\n radix2Fft(colRe, colIm, size, cos, sin);\n const cx = ox.cell[x]!, cx2 = ox.cell2[x]!, wx = ox.weight[x]!, wx2 = ox.weight2[x]!;\n for (let y = 0; y < size; y++) {\n const intensity = colRe[y]! * colRe[y]! + colIm[y]! * colIm[y]!;\n total += intensity;\n if (cx < 0) continue;\n const cy = oy.cell[y]!;\n if (cy < 0) continue;\n const cy2 = oy.cell2[y]!, wy = oy.weight[y]!, wy2 = oy.weight2[y]!;\n // Row index increases with image +Y (the quadrature's orientation).\n kernel[cy * w2 + cx]! += intensity * wx * wy; inside += intensity * wx * wy;\n if (cx2 >= 0) { kernel[cy * w2 + cx2]! += intensity * wx2 * wy; inside += intensity * wx2 * wy; }\n if (cy2 >= 0) {\n kernel[cy2 * w2 + cx]! += intensity * wx * wy2; inside += intensity * wx * wy2;\n if (cx2 >= 0) { kernel[cy2 * w2 + cx2]! += intensity * wx2 * wy2; inside += intensity * wx2 * wy2; }\n }\n }\n }\n if (!(total > 0) || !(inside > 0)) throw new InvalidScientificInputError(\"The catalogue lens PSF has no energy in its window.\");\n return { kernel, total, transform: size, phaseStep };\n }\n}\n\nfunction mirror(kernel: Float64Array, radius: number, flipX: boolean, flipY: boolean): Float64Array {\n const w = 2 * radius + 1, out = new Float64Array(kernel.length);\n for (let j = 0; j < w; j++) for (let i = 0; i < w; i++) out[(flipY ? w - 1 - j : j) * w + (flipX ? w - 1 - i : i)] = kernel[j * w + i]!;\n return out;\n}\n\n/** Thin-lens image distance z (mm), pupil diameter D = f/N (mm) and working f-number z/D at a finite focus. */\nfunction pupilGeometry(lens: ResolvedGenericLens, focusDistanceM: number): { z: number; D: number; workingF: number } {\n const f = lens.focalLengthMm, d = focusDistanceM * 1000;\n if (!(d > f)) throw new InvalidScientificInputError(\"The focus distance must exceed the focal length.\");\n const z = 1 / (1 / f - 1 / d), D = f / lens.character.fNumber;\n return { z, D, workingF: z / D };\n}\n\n/**\n * An upper bound of the aberration PSF's kernel radius in sites (the window is then narrowed to keep at most\n * {@link GENERIC_LENS_PSF_WINDOW_TRUNCATION} of every node's energy outside): the largest transverse ray aberration 2·N_w·|∂W/∂ρ| over the pupil at the frame\n * corner and every wavelength node, plus the lateral-colour shift, plus the Airy third dark ring 3.24·λ·N_w at 780 nm, rounded up\n * to whole sites (at least 1, at most {@link GENERIC_LENS_PSF_MAXIMUM_KERNEL_RADIUS_SITES}).\n */\nexport function genericLensPsfKernelRadius(input: { lens: ResolvedGenericLens; focusDistanceM: number; sitePitchMicrometers: number }): number {\n const { lens, sitePitchMicrometers: pitch } = input, { workingF } = pupilGeometry(lens, input.focusDistanceM);\n const longest = GENERIC_LENS_PSF_WAVELENGTHS_NM[GENERIC_LENS_PSF_WAVELENGTHS_NM.length - 1]! / 1000;\n let reachUm = 0;\n for (const nm of GENERIC_LENS_PSF_WAVELENGTHS_NM) {\n const shift = Math.abs(lens.character.lateralColor.fraction * lens.halfDiagonalMm * 1000 * genericLensDispersion(nm));\n reachUm = Math.max(reachUm, geometricRadiusMicrometers(lens, 1, nm / 1000, workingF) + shift);\n }\n reachUm += 3.24 * longest * workingF;\n return Math.min(GENERIC_LENS_PSF_MAXIMUM_KERNEL_RADIUS_SITES, Math.max(1, Math.ceil(reachUm / pitch - 0.5)));\n}\n\n/**\n * Builds the catalogue lens's sampled PSF profile for the environment PSF quadrature: 5 × 5 field nodes × 5 wavelengths, each\n * kernel on the site lattice. Engine-owned (parsed once). Deterministic: the same input gives the same profile.\n */\nexport function createGenericLensPsfProfile(input: GenericLensPsfInput): GenericLensPsf {\n const { lens, sitePitchMicrometers: pitch } = input;\n const f = lens.focalLengthMm, N = lens.character.fNumber, { z, D, workingF } = pupilGeometry(lens, input.focusDistanceM);\n const ex = input.fieldHalfExtentMm, fh = input.frameHalfMm;\n if (!(ex.x > fh.x / 2 && ex.y > fh.y / 2 && fh.x > 0 && fh.y > 0)) throw new InvalidScientificInputError(\"The PSF field extent must exceed half the frame.\");\n const xs = [0, fh.x / 2, ex.x], ys = [0, fh.y / 2, ex.y];\n const bound = genericLensPsfKernelRadius({ lens, focusDistanceM: input.focusDistanceM, sitePitchMicrometers: pitch });\n const quadrant = new Map<string, NodeResult>();\n let minimumTransform = Infinity, maximumTransform = 0, phaseStep = 0;\n for (const x of xs) for (const y of ys) for (const nm of GENERIC_LENS_PSF_WAVELENGTHS_NM) {\n const node = nodeKernel(lens, x, y, nm, workingF, D, z, pitch, bound);\n minimumTransform = Math.min(minimumTransform, node.transform);\n maximumTransform = Math.max(maximumTransform, node.transform); phaseStep = Math.max(phaseStep, node.phaseStep);\n quadrant.set(x + \":\" + y + \":\" + nm, node);\n }\n // The window: the smallest radius that keeps at most 1 % of every node's energy outside it (at most the bound).\n const outside = (r: number): number => {\n let worst = 0;\n for (const node of quadrant.values()) {\n let inside = 0;\n for (let j = bound - r; j <= bound + r; j++) for (let i = bound - r; i <= bound + r; i++) inside += node.kernel[j * (2 * bound + 1) + i]!;\n worst = Math.max(worst, 1 - inside / node.total);\n }\n return worst;\n };\n let radius = 1;\n while (radius < bound && outside(radius) > GENERIC_LENS_PSF_WINDOW_TRUNCATION) radius++;\n const truncated = Math.max(0, outside(radius));\n const crop = (node: NodeResult): Float64Array => {\n const w0 = 2 * bound + 1, w1 = 2 * radius + 1, out = new Float64Array(w1 * w1);\n let sum = 0;\n for (let j = 0; j < w1; j++) for (let i = 0; i < w1; i++) { const v = node.kernel[(j + bound - radius) * w0 + i + bound - radius]!; out[j * w1 + i] = v; sum += v; }\n for (let k = 0; k < out.length; k++) out[k] = out[k]! / sum;\n return out;\n };\n const extra = input.extraKernel, kernelRadius = radius + (extra ? extra.radius : 0), w = 2 * kernelRadius + 1;\n const fieldX = [-ex.x, -fh.x / 2, 0, fh.x / 2, ex.x], fieldY = [-ex.y, -fh.y / 2, 0, fh.y / 2, ex.y];\n const uncertainty = { kind: \"not-quantified\" as const, limitation: \"Generic catalogue lens PSF: Photivra's own Seidel coefficients, not a measured lens.\" };\n const nodes: LensSampledPsfGridNode[] = [];\n const focusDiopters = 1 / input.focusDistanceM;\n for (const x of fieldX) for (const y of fieldY) for (const nm of GENERIC_LENS_PSF_WAVELENGTHS_NM) {\n const base = quadrant.get(Math.abs(x) + \":\" + Math.abs(y) + \":\" + nm)!;\n let kernel = mirror(crop(base), radius, x < 0, y < 0);\n if (extra) kernel = convolveSiteKernels(kernel, radius, extra.weights, extra.radius);\n nodes.push({ nodeId: \"pv-\" + x.toFixed(6) + \"-\" + y.toFixed(6) + \"-\" + nm,\n coordinate: { focalLengthMm: f, focusDiopters, apertureFNumber: N, fieldXmm: x, fieldYmm: y, wavelengthNm: nm, signedDefocusImagePlaneMicrometers: 0 },\n kernel: { widthSamples: w, heightSamples: w, samplePitchMicrometersX: pitch, samplePitchMicrometersY: pitch, centerSampleX: kernelRadius, centerSampleY: kernelRadius,\n normalizedIntensity: Array.from(kernel) },\n bestFocusImagePlaneOffsetMicrometers: 0, relativePupilThroughputFactor: 1, evidence: input.evidence, uncertainty });\n }\n const profile: LensSampledPsfProfile = { schemaVersion: \"0.1.0\", profileId: \"photivra-\" + lens.lensId + \":psf\", profileVersion: \"1.0.0\", scientificStatus: \"approximation\",\n opticalDomain: \"lens-primary-optical-path-only\", coordinateSystem: \"image-plane-metric\", fieldAxes: \"+X right, +Y up\", kernelEnergyNormalization: \"unit-energy-shape\",\n interpolation: \"bounded-regular-grid-centroid-aligned\", throughputOwnership: \"separate-relative-pupil-throughput-factor\",\n responseIncludes: { diffraction: true, aberration: true, defocus: extra !== undefined, pupilClippingShape: false },\n sensorOpticalStackIncluded: false, sensorSamplingIncluded: false, reconstructionIncluded: false, strayLightIncluded: false,\n axes: { focalLengthMm: [f], focusDiopters: [focusDiopters], apertureFNumber: [N], fieldXmm: fieldX, fieldYmm: fieldY, wavelengthNm: [...GENERIC_LENS_PSF_WAVELENGTHS_NM],\n signedDefocusImagePlaneMicrometers: [0] }, nodes, evidence: input.evidence,\n limitations: [\"Generic catalogue lens (#549): scalar Fraunhofer PSF of Photivra's own Seidel wavefront with lateral colour, integrated over site cells; not a measured lens.\",\n \"Field and wavelength nodes are interpolated with centroid alignment; between nodes the PSF is a blend, not a recomputed PSF.\"] };\n markEngineOwnedLensSampledPsfProfile(profile);\n return { profile, aberrationKernelRadiusSites: radius, kernelRadiusSites: kernelRadius, maximumTruncatedEnergyFraction: truncated,\n transformSize: { minimum: minimumTransform, maximum: maximumTransform }, maximumPhaseStepWaves: phaseStep, fieldXmm: fieldX, fieldYmm: fieldY,\n wavelengthsNm: [...GENERIC_LENS_PSF_WAVELENGTHS_NM] };\n}\n"]}
1
+ {"version":3,"file":"generic-lens-psf.js","sourceRoot":"","sources":["../../src/optics/generic-lens-psf.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * The PSF of a generic catalogue lens (#549) on a sensor's site lattice, as a field- and wavelength-dependent sampled PSF\n * profile for the environment PSF quadrature (`simulateCapture` `lens.catalogue`).\n *\n * Model (an approximation): scalar Fraunhofer diffraction of a uniform circular pupil of diameter D = f/N carrying the\n * lens's Seidel wavefront (`resolveGenericLens`; the expansion of `createWavefrontPupilGrid`, Hopkins 1950; Wyant & Creath\n * 1992), propagated to the thin-lens image distance z (working f-number z/D; Goodman, Introduction to Fourier Optics, ch. 4-6).\n * U(x) = Σ_pupil exp(i·2π·W(u)/λ)·exp(−i·2π·x·u/(λ·z)) is evaluated with a zero-padded radix-2 FFT (Cooley & Tukey 1965) on\n * an image grid of pitch δ = min(λ·N_w/2, p/4) (p the site pitch), and |U|² is integrated over each site's square cell (exact\n * overlap of each δ-square with the cell). Lateral colour displaces the PSF radially by Δr(λ). The kernel window is (2R + 1)²\n * sites; the energy outside it is reported and put back by unit-sum renormalisation, as for `lens.diffraction`.\n *\n * Nodes: a 5 × 5 regular grid of field points (0, ±half the frame, ±the frame edge plus the kernel reach) × 5 wavelengths\n * (380, 450, 550, 650, 780 nm), each computed at its own field azimuth (no rotation of a radial node), interpolated by the\n * engine's centroid-aligned multilinear scheme. The quadrant x, y ≥ 0 is computed and mirrored (the Seidel PSF of a mirrored\n * field point is the mirrored PSF).\n *\n * Kernel orientation: a kernel's row index increases with image +Y, the orientation the environment PSF quadrature applies\n * (`sensorPsfSourcePoint`), so coma and lateral colour point away from the optical axis in the rendered image.\n */\n\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport type { EvidenceProvenance } from \"../core/evidence-provenance.js\";\nimport { genericLensDispersion, type ResolvedGenericLens } from \"../equipment/generic-lens-catalogue.js\";\nimport { markEngineOwnedLensSampledPsfProfile, type LensSampledPsfGridNode, type LensSampledPsfProfile } from \"./lens-psf-profile.js\";\nimport { convolveSiteKernels } from \"./defocus-disc-kernel.js\";\nimport { createDefocusBokehSiteKernel, type DefocusBokehSiteKernel, type ResolvedDefocusBokehOptions } from \"./defocus-bokeh-kernel.js\";\n\n/** Wavelength nodes of a catalogue PSF profile, nm (they span the facade's 380–780 nm quadrature). */\nexport const GENERIC_LENS_PSF_WAVELENGTHS_NM = /* @__PURE__ */ Object.freeze([380, 450, 550, 650, 780] as const);\n/** Largest kernel radius of the aberration PSF in sites (before any defocus disc is convolved in). */\nexport const GENERIC_LENS_PSF_MAXIMUM_KERNEL_RADIUS_SITES = 12;\n/** Largest kernel radius in sites of the catalogue PSF with a defocus disc convolved in (`simulateCapture` refuses more: cost). */\nexport const GENERIC_LENS_PSF_MAXIMUM_COMBINED_RADIUS_SITES = 16;\n/** Energy fraction a node may leave outside the chosen kernel window (it is put back by renormalisation and reported). */\nexport const GENERIC_LENS_PSF_WINDOW_TRUNCATION = 0.03;\n/** Largest FFT size per axis. */\nconst MAXIMUM_TRANSFORM = 2048;\n/** Largest optical-path step between neighbouring pupil samples, in waves (Nyquist is 0.5). */\nconst MAXIMUM_PHASE_STEP_WAVES = 0.35;\nconst DESIGN_WAVELENGTH_UM = 0.55;\n\nexport interface GenericLensPsfInput {\n /** The lens resolved at the capture's f-number and focus distance (`resolveGenericLens`). */\n lens: ResolvedGenericLens;\n /** Finite focus distance, m (the thin-lens image distance sets the propagation distance). */\n focusDistanceM: number;\n sitePitchMicrometers: number;\n /** Half extent of the field the profile must cover, mm (the frame's half width and height plus the PSF and query reach). */\n fieldHalfExtentMm: { x: number; y: number };\n /** The frame's half width and height, mm (the inner field nodes sit at half of them). */\n frameHalfMm: { x: number; y: number };\n /** Optional site kernel (2R_d + 1)² to convolve into each node, by its field point (mm, +Y up): the `lens.defocus` bokeh kernel. */\n extraKernel?: { radius: number; clipped?: boolean; at(fieldXmm: number, fieldYmm: number): Float64Array };\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface GenericLensPsf {\n profile: LensSampledPsfProfile;\n /** Radius of the aberration PSF window, sites, and of the applied kernel (with `extraKernel`). */\n aberrationKernelRadiusSites: number;\n kernelRadiusSites: number;\n /** Largest energy fraction outside the aberration window over the nodes (put back by renormalisation). */\n maximumTruncatedEnergyFraction: number;\n /** FFT sizes used (smallest, largest) and the largest pupil phase step, waves. */\n transformSize: { minimum: number; maximum: number };\n maximumPhaseStepWaves: number;\n /** Field node coordinates, mm, and wavelengths, nm. */\n fieldXmm: readonly number[];\n fieldYmm: readonly number[];\n wavelengthsNm: readonly number[];\n}\n\n/** In-place iterative radix-2 FFT, exp(−i·2π·k·m/n). */\nfunction radix2Fft(re: Float64Array, im: Float64Array, n: number, cos: Float64Array, sin: Float64Array): void {\n for (let i = 1, j = 0; i < n; i++) {\n let bit = n >> 1;\n for (; j & bit; bit >>= 1) j ^= bit;\n j ^= bit;\n if (i < j) { let t = re[i]!; re[i] = re[j]!; re[j] = t; t = im[i]!; im[i] = im[j]!; im[j] = t; }\n }\n for (let size = 2; size <= n; size <<= 1) {\n const half = size >> 1, step = n / size;\n for (let start = 0; start < n; start += size) for (let k = 0; k < half; k++) {\n const c = cos[k * step]!, s = sin[k * step]!, a = start + k, b = a + half;\n const tr = re[b]! * c + im[b]! * s, ti = im[b]! * c - re[b]! * s;\n re[b] = re[a]! - tr; im[b] = im[a]! - ti; re[a] = re[a]! + tr; im[a] = im[a]! + ti;\n }\n }\n}\n\n/** One axis's overlap of δ-squares centred at positions (s·δ + shift) with site cells [(i − ½)p, (i + ½)p], i ∈ [−R, R]. */\nfunction overlaps(count: number, delta: number, shift: number, pitch: number, radius: number): { cell: Int32Array; weight: Float64Array; cell2: Int32Array; weight2: Float64Array } {\n const cell = new Int32Array(count).fill(-1), weight = new Float64Array(count), cell2 = new Int32Array(count).fill(-1), weight2 = new Float64Array(count);\n for (let k = 0; k < count; k++) {\n const signed = k < count / 2 ? k : k - count, centre = signed * delta + shift, lo = centre - delta / 2, hi = centre + delta / 2;\n const first = Math.floor(lo / pitch + 0.5), last = Math.floor(hi / pitch + 0.5);\n for (let i = first; i <= last && i <= first + 1; i++) {\n if (i < -radius || i > radius) continue;\n const w = (Math.min(hi, (i + 0.5) * pitch) - Math.max(lo, (i - 0.5) * pitch)) / delta;\n if (w <= 0) continue;\n if (cell[k] === -1) { cell[k] = i + radius; weight[k] = w; } else { cell2[k] = i + radius; weight2[k] = w; }\n }\n }\n return { cell, weight, cell2, weight2 };\n}\n\n/** A node's energy per site cell over the (2R₀ + 1)² window (not normalised) and the whole period's energy. */\ninterface NodeResult { kernel: Float64Array; total: number; transform: number; phaseStep: number }\n\n/** Seidel OPD (µm) at normalised pupil (px, py) for a field point at height H and azimuth φ, at wavelength λ (µm). */\nfunction opdMicrometers(lens: ResolvedGenericLens, H: number, cosPhi: number, sinPhi: number, lambdaUm: number, px: number, py: number): number {\n const a = lens.character.aberrations, r2 = px * px + py * py, along = px * cosPhi + py * sinPhi;\n const defocus = a.balancingDefocusWaves + a.axialColorWaves * genericLensDispersion(lambdaUm * 1000);\n // Positive coma W131 sends the comet's flare away from the axis in the image (H ρ³ cos(θ − φ), with the FFT sign above).\n return DESIGN_WAVELENGTH_UM * (defocus * r2 + a.sphericalWaves * r2 * r2 + a.comaWaves * H * r2 * along + a.astigmatismWaves * H * H * along * along + a.fieldCurvatureWaves * H * H * r2);\n}\n\n/** Largest transverse ray aberration 2·N_w·|∂W/∂ρ| (µm) over the pupil, from a 33 × 33 grid. */\nfunction geometricRadiusMicrometers(lens: ResolvedGenericLens, H: number, lambdaUm: number, workingF: number): number {\n let largest = 0;\n const n = 33, h = 1e-4;\n for (let j = 0; j < n; j++) for (let i = 0; i < n; i++) {\n const px = -1 + 2 * i / (n - 1), py = -1 + 2 * j / (n - 1);\n if (px * px + py * py > 1) continue;\n const gx = (opdMicrometers(lens, H, 1, 0, lambdaUm, px + h, py) - opdMicrometers(lens, H, 1, 0, lambdaUm, px - h, py)) / (2 * h);\n const gy = (opdMicrometers(lens, H, 1, 0, lambdaUm, px, py + h) - opdMicrometers(lens, H, 1, 0, lambdaUm, px, py - h)) / (2 * h);\n largest = Math.max(largest, Math.hypot(gx, gy));\n }\n return 2 * workingF * largest;\n}\n\nfunction nodeKernel(lens: ResolvedGenericLens, xMm: number, yMm: number, lambdaNm: number, workingF: number, pupilDiameterMm: number, zMm: number,\n pitch: number, radius: number): NodeResult {\n const lambdaUm = lambdaNm / 1000, r = Math.hypot(xMm, yMm), H = Math.min(1, r / lens.halfDiagonalMm);\n const cosPhi = r > 0 ? xMm / r : 1, sinPhi = r > 0 ? yMm / r : 0;\n // Lateral colour: radial displacement L·R·H·D(λ), µm.\n const shift = lens.character.lateralColor.fraction * lens.halfDiagonalMm * 1000 * H * genericLensDispersion(lambdaNm);\n const delta = Math.min(lambdaUm * workingF / 2, pitch / 4);\n let size = 64;\n // The FFT period must hold the window, or (when the PSF is much smaller than the window, for large pixels) the PSF itself:\n // the geometric blur plus 16·λ·N_w of Airy rings (the energy beyond, about 1 %, folds back into the period).\n const psfExtentUm = 2 * (geometricRadiusMicrometers(lens, H, lambdaUm, workingF) + 16 * lambdaUm * workingF);\n while (size * delta < Math.min(2.5 * (radius + 0.5) * pitch, psfExtentUm) + 2 * Math.abs(shift)) size *= 2;\n for (;;) {\n if (size > MAXIMUM_TRANSFORM) throw new InvalidScientificInputError(\"The catalogue lens PSF needs an FFT larger than \" + MAXIMUM_TRANSFORM + \" per axis.\");\n // Pupil pitch: δ · p_pupil = λ·z / size (mm).\n const pupilPitchMm = lambdaUm / 1000 * zMm / (size * delta / 1000), half = pupilDiameterMm / 2, reach = Math.floor(half / pupilPitchMm);\n const re = new Float64Array(size * size), im = new Float64Array(size * size), rowUsed = new Uint8Array(size);\n let open = 0, phaseStep = 0;\n const opd = new Float64Array((2 * reach + 1) * (2 * reach + 1)).fill(NaN);\n for (let v = -reach; v <= reach; v++) for (let u = -reach; u <= reach; u++) {\n const px = u * pupilPitchMm / half, py = v * pupilPitchMm / half;\n if (px * px + py * py > 1 + 1e-12) continue;\n const w = opdMicrometers(lens, H, cosPhi, sinPhi, lambdaUm, px, py), phase = 2 * Math.PI * w / lambdaUm;\n opd[(v + reach) * (2 * reach + 1) + u + reach] = w;\n const index = ((v + size) % size) * size + (u + size) % size;\n re[index] = Math.cos(phase); im[index] = Math.sin(phase); rowUsed[(v + size) % size] = 1; open++;\n }\n const width = 2 * reach + 1;\n for (let j = 0; j < width; j++) for (let i = 0; i < width; i++) {\n const w = opd[j * width + i]!;\n if (Number.isNaN(w)) continue;\n if (i + 1 < width && !Number.isNaN(opd[j * width + i + 1]!)) phaseStep = Math.max(phaseStep, Math.abs(opd[j * width + i + 1]! - w) / lambdaUm);\n if (j + 1 < width && !Number.isNaN(opd[(j + 1) * width + i]!)) phaseStep = Math.max(phaseStep, Math.abs(opd[(j + 1) * width + i]! - w) / lambdaUm);\n }\n if (open < 9) throw new InvalidScientificInputError(\"The catalogue lens PSF pupil has fewer than 9 samples.\");\n if (phaseStep > MAXIMUM_PHASE_STEP_WAVES) { size *= 2; continue; }\n const cos = new Float64Array(size / 2), sin = new Float64Array(size / 2);\n for (let k = 0; k < size / 2; k++) { cos[k] = Math.cos(2 * Math.PI * k / size); sin[k] = Math.sin(2 * Math.PI * k / size); }\n const rowRe = new Float64Array(size), rowIm = new Float64Array(size);\n for (let y = 0; y < size; y++) {\n if (!rowUsed[y]) continue;\n rowRe.set(re.subarray(y * size, (y + 1) * size)); rowIm.set(im.subarray(y * size, (y + 1) * size));\n radix2Fft(rowRe, rowIm, size, cos, sin);\n re.set(rowRe, y * size); im.set(rowIm, y * size);\n }\n const colRe = new Float64Array(size), colIm = new Float64Array(size);\n const ox = overlaps(size, delta, shift * cosPhi, pitch, radius), oy = overlaps(size, delta, shift * sinPhi, pitch, radius);\n const w2 = 2 * radius + 1, kernel = new Float64Array(w2 * w2);\n let total = 0, inside = 0;\n for (let x = 0; x < size; x++) {\n for (let y = 0; y < size; y++) { colRe[y] = re[y * size + x]!; colIm[y] = im[y * size + x]!; }\n radix2Fft(colRe, colIm, size, cos, sin);\n const cx = ox.cell[x]!, cx2 = ox.cell2[x]!, wx = ox.weight[x]!, wx2 = ox.weight2[x]!;\n for (let y = 0; y < size; y++) {\n const intensity = colRe[y]! * colRe[y]! + colIm[y]! * colIm[y]!;\n total += intensity;\n if (cx < 0) continue;\n const cy = oy.cell[y]!;\n if (cy < 0) continue;\n const cy2 = oy.cell2[y]!, wy = oy.weight[y]!, wy2 = oy.weight2[y]!;\n // Row index increases with image +Y (the quadrature's orientation).\n kernel[cy * w2 + cx]! += intensity * wx * wy; inside += intensity * wx * wy;\n if (cx2 >= 0) { kernel[cy * w2 + cx2]! += intensity * wx2 * wy; inside += intensity * wx2 * wy; }\n if (cy2 >= 0) {\n kernel[cy2 * w2 + cx]! += intensity * wx * wy2; inside += intensity * wx * wy2;\n if (cx2 >= 0) { kernel[cy2 * w2 + cx2]! += intensity * wx2 * wy2; inside += intensity * wx2 * wy2; }\n }\n }\n }\n if (!(total > 0) || !(inside > 0)) throw new InvalidScientificInputError(\"The catalogue lens PSF has no energy in its window.\");\n return { kernel, total, transform: size, phaseStep };\n }\n}\n\nfunction mirror(kernel: Float64Array, radius: number, flipX: boolean, flipY: boolean): Float64Array {\n const w = 2 * radius + 1, out = new Float64Array(kernel.length);\n for (let j = 0; j < w; j++) for (let i = 0; i < w; i++) out[(flipY ? w - 1 - j : j) * w + (flipX ? w - 1 - i : i)] = kernel[j * w + i]!;\n return out;\n}\n\n/** Thin-lens image distance z (mm), pupil diameter D = f/N (mm) and working f-number z/D at a finite focus. */\nfunction pupilGeometry(lens: ResolvedGenericLens, focusDistanceM: number): { z: number; D: number; workingF: number } {\n const f = lens.focalLengthMm, d = focusDistanceM * 1000;\n if (!(d > f)) throw new InvalidScientificInputError(\"The focus distance must exceed the focal length.\");\n const z = 1 / (1 / f - 1 / d), D = f / lens.character.fNumber;\n return { z, D, workingF: z / D };\n}\n\n/**\n * An upper bound of the aberration PSF's kernel radius in sites (the window is then narrowed to keep at most\n * {@link GENERIC_LENS_PSF_WINDOW_TRUNCATION} of every node's energy outside): the largest transverse ray aberration 2·N_w·|∂W/∂ρ| over the pupil at the frame\n * corner and every wavelength node, plus the lateral-colour shift, plus the Airy third dark ring 3.24·λ·N_w at 780 nm, rounded up\n * to whole sites (at least 1, at most {@link GENERIC_LENS_PSF_MAXIMUM_KERNEL_RADIUS_SITES}).\n */\nexport function genericLensPsfKernelRadius(input: { lens: ResolvedGenericLens; focusDistanceM: number; sitePitchMicrometers: number }): number {\n const { lens, sitePitchMicrometers: pitch } = input, { workingF } = pupilGeometry(lens, input.focusDistanceM);\n const longest = GENERIC_LENS_PSF_WAVELENGTHS_NM[GENERIC_LENS_PSF_WAVELENGTHS_NM.length - 1]! / 1000;\n let reachUm = 0;\n for (const nm of GENERIC_LENS_PSF_WAVELENGTHS_NM) {\n const shift = Math.abs(lens.character.lateralColor.fraction * lens.halfDiagonalMm * 1000 * genericLensDispersion(nm));\n reachUm = Math.max(reachUm, geometricRadiusMicrometers(lens, 1, nm / 1000, workingF) + shift);\n }\n reachUm += 3.24 * longest * workingF;\n return Math.min(GENERIC_LENS_PSF_MAXIMUM_KERNEL_RADIUS_SITES, Math.max(1, Math.ceil(reachUm / pitch - 0.5)));\n}\n\n/**\n * Builds the catalogue lens's sampled PSF profile for the environment PSF quadrature: 5 × 5 field nodes × 5 wavelengths, each\n * kernel on the site lattice. Engine-owned (parsed once). Deterministic: the same input gives the same profile.\n */\nexport function createGenericLensPsfProfile(input: GenericLensPsfInput): GenericLensPsf {\n const { lens, sitePitchMicrometers: pitch } = input;\n const f = lens.focalLengthMm, N = lens.character.fNumber, { z, D, workingF } = pupilGeometry(lens, input.focusDistanceM);\n const ex = input.fieldHalfExtentMm, fh = input.frameHalfMm;\n if (!(ex.x > fh.x / 2 && ex.y > fh.y / 2 && fh.x > 0 && fh.y > 0)) throw new InvalidScientificInputError(\"The PSF field extent must exceed half the frame.\");\n const xs = [0, fh.x / 2, ex.x], ys = [0, fh.y / 2, ex.y];\n const bound = genericLensPsfKernelRadius({ lens, focusDistanceM: input.focusDistanceM, sitePitchMicrometers: pitch });\n const quadrant = new Map<string, NodeResult>();\n let minimumTransform = Infinity, maximumTransform = 0, phaseStep = 0;\n for (const x of xs) for (const y of ys) for (const nm of GENERIC_LENS_PSF_WAVELENGTHS_NM) {\n const node = nodeKernel(lens, x, y, nm, workingF, D, z, pitch, bound);\n minimumTransform = Math.min(minimumTransform, node.transform);\n maximumTransform = Math.max(maximumTransform, node.transform); phaseStep = Math.max(phaseStep, node.phaseStep);\n quadrant.set(x + \":\" + y + \":\" + nm, node);\n }\n // The window: the smallest radius that keeps at most 1 % of every node's energy outside it (at most the bound).\n const outside = (r: number): number => {\n let worst = 0;\n for (const node of quadrant.values()) {\n let inside = 0;\n for (let j = bound - r; j <= bound + r; j++) for (let i = bound - r; i <= bound + r; i++) inside += node.kernel[j * (2 * bound + 1) + i]!;\n worst = Math.max(worst, 1 - inside / node.total);\n }\n return worst;\n };\n let radius = 1;\n while (radius < bound && outside(radius) > GENERIC_LENS_PSF_WINDOW_TRUNCATION) radius++;\n const truncated = Math.max(0, outside(radius));\n const crop = (node: NodeResult): Float64Array => {\n const w0 = 2 * bound + 1, w1 = 2 * radius + 1, out = new Float64Array(w1 * w1);\n let sum = 0;\n for (let j = 0; j < w1; j++) for (let i = 0; i < w1; i++) { const v = node.kernel[(j + bound - radius) * w0 + i + bound - radius]!; out[j * w1 + i] = v; sum += v; }\n for (let k = 0; k < out.length; k++) out[k] = out[k]! / sum;\n return out;\n };\n const extra = input.extraKernel, kernelRadius = radius + (extra ? extra.radius : 0), w = 2 * kernelRadius + 1;\n const fieldX = [-ex.x, -fh.x / 2, 0, fh.x / 2, ex.x], fieldY = [-ex.y, -fh.y / 2, 0, fh.y / 2, ex.y];\n const uncertainty = { kind: \"not-quantified\" as const, limitation: \"Generic catalogue lens PSF: Photivra's own Seidel coefficients, not a measured lens.\" };\n const nodes: LensSampledPsfGridNode[] = [];\n const focusDiopters = 1 / input.focusDistanceM;\n for (const x of fieldX) for (const y of fieldY) for (const nm of GENERIC_LENS_PSF_WAVELENGTHS_NM) {\n const base = quadrant.get(Math.abs(x) + \":\" + Math.abs(y) + \":\" + nm)!;\n let kernel = mirror(crop(base), radius, x < 0, y < 0);\n if (extra) kernel = convolveSiteKernels(kernel, radius, extra.at(x, y), extra.radius);\n nodes.push({ nodeId: \"pv-\" + x.toFixed(6) + \"-\" + y.toFixed(6) + \"-\" + nm,\n coordinate: { focalLengthMm: f, focusDiopters, apertureFNumber: N, fieldXmm: x, fieldYmm: y, wavelengthNm: nm, signedDefocusImagePlaneMicrometers: 0 },\n kernel: { widthSamples: w, heightSamples: w, samplePitchMicrometersX: pitch, samplePitchMicrometersY: pitch, centerSampleX: kernelRadius, centerSampleY: kernelRadius,\n normalizedIntensity: Array.from(kernel) },\n bestFocusImagePlaneOffsetMicrometers: 0, relativePupilThroughputFactor: 1, evidence: input.evidence, uncertainty });\n }\n const profile: LensSampledPsfProfile = { schemaVersion: \"0.1.0\", profileId: \"photivra-\" + lens.lensId + \":psf\", profileVersion: \"1.0.0\", scientificStatus: \"approximation\",\n opticalDomain: \"lens-primary-optical-path-only\", coordinateSystem: \"image-plane-metric\", fieldAxes: \"+X right, +Y up\", kernelEnergyNormalization: \"unit-energy-shape\",\n interpolation: \"bounded-regular-grid-centroid-aligned\", throughputOwnership: \"separate-relative-pupil-throughput-factor\",\n responseIncludes: { diffraction: true, aberration: true, defocus: extra !== undefined, pupilClippingShape: extra?.clipped === true },\n sensorOpticalStackIncluded: false, sensorSamplingIncluded: false, reconstructionIncluded: false, strayLightIncluded: false,\n axes: { focalLengthMm: [f], focusDiopters: [focusDiopters], apertureFNumber: [N], fieldXmm: fieldX, fieldYmm: fieldY, wavelengthNm: [...GENERIC_LENS_PSF_WAVELENGTHS_NM],\n signedDefocusImagePlaneMicrometers: [0] }, nodes, evidence: input.evidence,\n limitations: [\"Generic catalogue lens (#549): scalar Fraunhofer PSF of Photivra's own Seidel wavefront with lateral colour, integrated over site cells; not a measured lens.\",\n \"Field and wavelength nodes are interpolated with centroid alignment; between nodes the PSF is a blend, not a recomputed PSF.\"] };\n markEngineOwnedLensSampledPsfProfile(profile);\n return { profile, aberrationKernelRadiusSites: radius, kernelRadiusSites: kernelRadius, maximumTruncatedEnergyFraction: truncated,\n transformSize: { minimum: minimumTransform, maximum: maximumTransform }, maximumPhaseStepWaves: phaseStep, fieldXmm: fieldX, fieldYmm: fieldY,\n wavelengthsNm: [...GENERIC_LENS_PSF_WAVELENGTHS_NM] };\n}\n\n/**\n * #567: the catalogue lens's own bokeh kernel for `lens.defocus` (#553's shaped kernel with `lens.character.bokeh`), as the\n * PSF's field-dependent extra kernel. The defocus is referred to the lens's focus, the balanced one of its PSF (W020 = −W040):\n * the ray map (σc/2 + bρ²)·P of the paraxial focus gains −(b/2)·P, so the kernel is #553's for the signed blur σc − b. Rows are\n * flipped from #553's (+Y down) to the profile's (+Y up). With a cat's eye each field point (tangent x/f, y/f: the rectilinear\n * chief ray, distortion neglected) has its own kernel, padded to the axis kernel's radius (clipping only narrows the blur). Each\n * call builds its kernel (the profile calls it once per field and wavelength node: 125 small kernels). `catsEye` false leaves it out.\n */\nexport function genericLensBokehKernel(lens: ResolvedGenericLens, diameterSites: number, side: 1 | -1, pitch: number, catsEye: boolean):\n { axis: DefocusBokehSiteKernel; radius: number; clipped: boolean; at(fieldXmm: number, fieldYmm: number): Float64Array } {\n const b = lens.character.bokeh, options = (catsEye ? b : { blades: b.blades, sphericalAberration: b.sphericalAberration }) as ResolvedDefocusBokehOptions, N = lens.character.fNumber, f = lens.focalLengthMm;\n const s = side * diameterSites - 8 * N * options.sphericalAberration!.w040Micrometers / pitch;\n const build = (x: number, y: number): DefocusBokehSiteKernel => createDefocusBokehSiteKernel({ diameterSites: Math.abs(s), side: s < 0 ? -1 : 1, fNumber: N,\n focalLengthMm: f, pitchMicrometers: pitch, options, field: { x: x / f, y: y / f } });\n const axis = build(0, 0), R = axis.radius, w = 2 * R + 1;\n return { axis, radius: R, clipped: !!options.catsEye, at(x, y): Float64Array {\n const k = options.catsEye ? build(x, y) : axis, r = k.radius, out = new Float64Array(w * w);\n for (let j = -r; j <= r; j++) for (let i = -r; i <= r; i++) out[(R - j) * w + i + R] = k.weights[(j + r) * k.width + i + r]!;\n return out;\n } };\n}\n"]}
@@ -25,6 +25,19 @@ import { type SpectralWavelengthBasis } from "../core/spectral.js";
25
25
  import { type FrontOfLensFilterProfile } from "./front-of-lens-filter.js";
26
26
  import type { IlluminationVignetting } from "./illumination-vignetting.js";
27
27
  import { type SceneRadianceEvaluationRequest, type SceneRadianceEvaluationResult } from "../schema/scene-radiance.js";
28
+ /**
29
+ * The scope fields every engine-built scene-to-sensor profile declares, in this order (shared by the capture facade and the
30
+ * generic tier presets): the bridge leaves distortion area mapping and PSF redistribution downstream and models none of the rest.
31
+ */
32
+ export declare const SCENE_TO_SENSOR_BRIDGE_SCOPE: Readonly<{
33
+ distortionAreaMappingOwnership: "not-applied-by-bridge";
34
+ psfRedistributionOwnership: "downstream-normalized-energy-redistribution";
35
+ sensorOpticalStackIncluded: false;
36
+ strayLightIncluded: false;
37
+ polarizationModeled: false;
38
+ wavelengthChangingBehaviorModeled: false;
39
+ volumetricScatteringModeled: false;
40
+ }>;
28
41
  export declare const SCENE_TO_SENSOR_IRRADIANCE_PROFILE_SCHEMA_VERSION: "0.1.0";
29
42
  export type OpticalBridgeScientificStatus = "calibrated" | "approximation";
30
43
  export type OpticalBridgeUncertainty = {
@@ -30,6 +30,13 @@ import { calculateThinLensImageDistance } from "./thin-lens.js";
30
30
  import { parseSceneRadianceEvaluationRequest, parseSceneRadianceEvaluationResult } from "../schema/scene-radiance.js";
31
31
  import { requireInputKeys, rejectUnknownVariantFields, UNCERTAINTY_VARIANT_FIELDS, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, parseConfigScientificStatus as parseScientificStatus, requireInputPositiveFinite as requirePositiveFiniteScientific, parseConfigLimitations as parseLimitations, requireConfigFiniteAboveZero as requirePositiveFinite } from "../core/record-validation.js";
32
32
  import { requireFraction } from "../color/white-balance.js";
33
+ /**
34
+ * The scope fields every engine-built scene-to-sensor profile declares, in this order (shared by the capture facade and the
35
+ * generic tier presets): the bridge leaves distortion area mapping and PSF redistribution downstream and models none of the rest.
36
+ */
37
+ export const SCENE_TO_SENSOR_BRIDGE_SCOPE = /* @__PURE__ */ Object.freeze({ distortionAreaMappingOwnership: "not-applied-by-bridge",
38
+ psfRedistributionOwnership: "downstream-normalized-energy-redistribution", sensorOpticalStackIncluded: false, strayLightIncluded: false,
39
+ polarizationModeled: false, wavelengthChangingBehaviorModeled: false, volumetricScatteringModeled: false });
33
40
  export const SCENE_TO_SENSOR_IRRADIANCE_PROFILE_SCHEMA_VERSION = "0.1.0";
34
41
  function parseUncertainty(value, path) {
35
42
  const record = requireRecord(value, path, null);