@photivra/engine 2.21.0 → 2.22.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 (169) hide show
  1. package/CHANGELOG.md +118 -1
  2. package/CITATION.cff +1 -1
  3. package/README.md +6 -6
  4. package/SECURITY.md +1 -1
  5. package/THIRD_PARTY.md +11 -0
  6. package/dist/capture/c2pa-embed.d.ts +116 -0
  7. package/dist/capture/c2pa-embed.js +493 -0
  8. package/dist/capture/c2pa-embed.js.map +1 -0
  9. package/dist/capture/dng-import.d.ts +73 -8
  10. package/dist/capture/dng-import.js +315 -80
  11. package/dist/capture/dng-import.js.map +1 -1
  12. package/dist/capture/dng-opcodes.d.ts +96 -0
  13. package/dist/capture/dng-opcodes.js +391 -0
  14. package/dist/capture/dng-opcodes.js.map +1 -0
  15. package/dist/capture/dng-profile-maps.d.ts +99 -0
  16. package/dist/capture/dng-profile-maps.js +381 -0
  17. package/dist/capture/dng-profile-maps.js.map +1 -0
  18. package/dist/capture/dng-stage-image.d.ts +23 -0
  19. package/dist/capture/dng-stage-image.js +65 -0
  20. package/dist/capture/dng-stage-image.js.map +1 -0
  21. package/dist/capture/jpeg-xl-tiles.d.ts +22 -0
  22. package/dist/capture/jpeg-xl-tiles.js +151 -0
  23. package/dist/capture/jpeg-xl-tiles.js.map +1 -0
  24. package/dist/capture/lossy-jpeg.d.ts +17 -0
  25. package/dist/capture/lossy-jpeg.js +369 -0
  26. package/dist/capture/lossy-jpeg.js.map +1 -0
  27. package/dist/capture/native-raw-development.d.ts +2 -1
  28. package/dist/capture/native-raw-development.js.map +1 -1
  29. package/dist/color/neighbor-highlight-reconstruction.d.ts +66 -0
  30. package/dist/color/neighbor-highlight-reconstruction.js +234 -0
  31. package/dist/color/neighbor-highlight-reconstruction.js.map +1 -0
  32. package/dist/color/sensor-color-development.d.ts +5 -0
  33. package/dist/color/sensor-color-development.js +7 -1
  34. package/dist/color/sensor-color-development.js.map +1 -1
  35. package/dist/color/spectral-spikiness.d.ts +11 -0
  36. package/dist/color/spectral-spikiness.js +23 -0
  37. package/dist/color/spectral-spikiness.js.map +1 -0
  38. package/dist/core/execution-error.d.ts +21 -0
  39. package/dist/core/execution-error.js +12 -0
  40. package/dist/core/execution-error.js.map +1 -0
  41. package/dist/core/version.d.ts +1 -1
  42. package/dist/core/version.js +1 -1
  43. package/dist/core/version.js.map +1 -1
  44. package/dist/facade/catalogue-lens-signal.d.ts +26 -1
  45. package/dist/facade/catalogue-lens-signal.js +25 -7
  46. package/dist/facade/catalogue-lens-signal.js.map +1 -1
  47. package/dist/facade/diffraction-provider.d.ts +1 -1
  48. package/dist/facade/diffraction-provider.js +4 -4
  49. package/dist/facade/diffraction-provider.js.map +1 -1
  50. package/dist/facade/display-view-gpu-session.js +38 -6
  51. package/dist/facade/display-view-gpu-session.js.map +1 -1
  52. package/dist/facade/display-view-gpu.d.ts +13 -5
  53. package/dist/facade/display-view-gpu.js.map +1 -1
  54. package/dist/facade/display-view-normal.d.ts +15 -0
  55. package/dist/facade/display-view-normal.js +44 -0
  56. package/dist/facade/display-view-normal.js.map +1 -0
  57. package/dist/facade/display-view-rendering.d.ts +97 -0
  58. package/dist/facade/display-view-rendering.js +598 -0
  59. package/dist/facade/display-view-rendering.js.map +1 -0
  60. package/dist/facade/display-view.d.ts +37 -65
  61. package/dist/facade/display-view.js +147 -476
  62. package/dist/facade/display-view.js.map +1 -1
  63. package/dist/facade/expected-signal-setup.js +2 -2
  64. package/dist/facade/expected-signal-setup.js.map +1 -1
  65. package/dist/facade/fast-methods.d.ts +1 -1
  66. package/dist/facade/fast-methods.js +37 -8
  67. package/dist/facade/fast-methods.js.map +1 -1
  68. package/dist/facade/generic-lens-capture.d.ts +1 -1
  69. package/dist/facade/generic-lens-capture.js +1 -1
  70. package/dist/facade/generic-lens-capture.js.map +1 -1
  71. package/dist/facade/image-plane.js +41 -10
  72. package/dist/facade/image-plane.js.map +1 -1
  73. package/dist/facade/on-demand-kits.d.ts +14 -0
  74. package/dist/facade/on-demand-kits.js +36 -0
  75. package/dist/facade/on-demand-kits.js.map +1 -0
  76. package/dist/facade/opt-in-kit.d.ts +9 -0
  77. package/dist/facade/opt-in-kit.js +11 -0
  78. package/dist/facade/opt-in-kit.js.map +1 -0
  79. package/dist/facade/quality-kit.d.ts +21 -0
  80. package/dist/facade/quality-kit.js +23 -0
  81. package/dist/facade/quality-kit.js.map +1 -0
  82. package/dist/facade/quality-paths.d.ts +22 -0
  83. package/dist/facade/quality-paths.js +44 -0
  84. package/dist/facade/quality-paths.js.map +1 -0
  85. package/dist/facade/scene-radiance.d.ts +18 -2
  86. package/dist/facade/scene-radiance.js +6 -4
  87. package/dist/facade/scene-radiance.js.map +1 -1
  88. package/dist/facade/simulate-capture.d.ts +32 -13
  89. package/dist/facade/simulate-capture.js +162 -69
  90. package/dist/facade/simulate-capture.js.map +1 -1
  91. package/dist/facade/simulate-display-view.d.ts +10 -12
  92. package/dist/facade/simulate-display-view.js +57 -48
  93. package/dist/facade/simulate-display-view.js.map +1 -1
  94. package/dist/gpu/display-view-gpu-renderer.d.ts +43 -0
  95. package/dist/gpu/display-view-gpu-renderer.js +134 -0
  96. package/dist/gpu/display-view-gpu-renderer.js.map +1 -0
  97. package/dist/gpu/display-view-image-material-module.d.ts +3 -2
  98. package/dist/gpu/display-view-image-material-module.js +25 -3
  99. package/dist/gpu/display-view-image-material-module.js.map +1 -1
  100. package/dist/gpu/display-view-image-quality.d.ts +43 -1
  101. package/dist/gpu/display-view-image-quality.js +256 -11
  102. package/dist/gpu/display-view-image-quality.js.map +1 -1
  103. package/dist/gpu/display-view-quality-gpu.d.ts +13 -64
  104. package/dist/gpu/display-view-quality-gpu.js +60 -249
  105. package/dist/gpu/display-view-quality-gpu.js.map +1 -1
  106. package/dist/gpu/display-view-speed-gpu.d.ts +16 -16
  107. package/dist/gpu/display-view-speed-gpu.js +50 -12
  108. package/dist/gpu/display-view-speed-gpu.js.map +1 -1
  109. package/dist/gpu/image-kernel-accelerator.js +3 -0
  110. package/dist/gpu/image-kernel-accelerator.js.map +1 -1
  111. package/dist/gpu/image-kernel-execution.d.ts +2 -13
  112. package/dist/gpu/image-kernel-execution.js +2 -10
  113. package/dist/gpu/image-kernel-execution.js.map +1 -1
  114. package/dist/gpu/wgsl-display-view-coupled-stub.d.ts +8 -0
  115. package/dist/gpu/wgsl-display-view-coupled-stub.js +21 -0
  116. package/dist/gpu/wgsl-display-view-coupled-stub.js.map +1 -0
  117. package/dist/gpu/wgsl-display-view-coupled.d.ts +88 -0
  118. package/dist/gpu/wgsl-display-view-coupled.js +353 -0
  119. package/dist/gpu/wgsl-display-view-coupled.js.map +1 -0
  120. package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +4 -9
  121. package/dist/gpu/wgsl-display-view-quality-kernel.js +109 -111
  122. package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
  123. package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +1 -41
  124. package/dist/gpu/wgsl-display-view-speed-kernel.js +71 -8
  125. package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
  126. package/dist/index.d.ts +11 -3
  127. package/dist/index.js +9 -1
  128. package/dist/index.js.map +1 -1
  129. package/dist/output/camera-channel-response.d.ts +50 -0
  130. package/dist/output/camera-channel-response.js +69 -0
  131. package/dist/output/camera-channel-response.js.map +1 -0
  132. package/dist/output/native-capture-sdr.js +5 -2
  133. package/dist/output/native-capture-sdr.js.map +1 -1
  134. package/dist/output/sdr-rendering.d.ts +18 -1
  135. package/dist/output/sdr-rendering.js +39 -2
  136. package/dist/output/sdr-rendering.js.map +1 -1
  137. package/dist/sensor/native-sensor-report.d.ts +10 -0
  138. package/dist/sensor/native-sensor-report.js +16 -0
  139. package/dist/sensor/native-sensor-report.js.map +1 -0
  140. package/dist/sensor/sensor-characteristics.d.ts +81 -13
  141. package/dist/sensor/sensor-characteristics.js +10 -6
  142. package/dist/sensor/sensor-characteristics.js.map +1 -1
  143. package/docs/API_REFERENCE.md +117 -4
  144. package/docs/QUICK_START.md +37 -8
  145. package/docs/USAGE.md +104 -22
  146. package/docs/api/capture-c2pa-embed.md +177 -0
  147. package/docs/api/capture-dng-import.md +86 -10
  148. package/docs/api/capture-dng-opcodes.md +93 -0
  149. package/docs/api/capture-dng-profile-maps.md +141 -0
  150. package/docs/api/capture-dng-stage-image.md +43 -0
  151. package/docs/api/capture-jpeg-xl-tiles.md +33 -0
  152. package/docs/api/capture-lossy-jpeg.md +41 -0
  153. package/docs/api/capture-native-raw-development.md +2 -1
  154. package/docs/api/core-execution-error.md +43 -0
  155. package/docs/api/core-version.md +1 -1
  156. package/docs/api/exports.json +255 -5
  157. package/docs/api/facade-display-view-gpu.md +5 -2
  158. package/docs/api/facade-display-view.md +11 -15
  159. package/docs/api/facade-fast-methods.md +38 -9
  160. package/docs/api/facade-quality-paths.md +24 -0
  161. package/docs/api/facade-scene-radiance.md +1 -1
  162. package/docs/api/facade-simulate-capture.md +24 -7
  163. package/docs/api/facade-simulate-display-view.md +10 -12
  164. package/docs/api/gpu-image-kernel-execution.md +0 -36
  165. package/docs/api/output-camera-channel-response.md +55 -0
  166. package/docs/api/output-sdr-rendering.md +6 -1
  167. package/docs/api/sensor-sensor-characteristics.md +54 -2
  168. package/llms.txt +1 -0
  169. package/package.json +6 -5
@@ -37,6 +37,24 @@ import { prepareIlluminationVignettingThroughput } from "../optics/illumination-
37
37
  import { kernelCentroid, resolveLensSampledPsfKernel } from "../optics/lens-psf-profile.js";
38
38
  /** Fewest grid cells between neighboring profile field nodes (10 since #589: with 4, 0.4 % of quick frames failed the run-time check). */
39
39
  export const CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS = 10;
40
+ /**
41
+ * #603 (2.22.0): the fewest cells on a fast request (on screen: 2.20.0's grid, its run-time fallbacks to the exact method included);
42
+ * the full grid, {@link CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS}, on an exact one (the exports and the calculator).
43
+ */
44
+ export const CATALOGUE_FAST_GRID_SPEED_SUBDIVISIONS = 4;
45
+ /**
46
+ * #603 (owner decision 2026-11-11): the lenses that keep the full grid on fast requests too, because the 4-cell grid's run-time
47
+ * fallbacks to the exact method made their fast frames slower on average. Measured November 11, 2026 (arm64, Node.js 24; every
48
+ * catalogue lens but the phone lenses, wide open and at max(f/8, widest), Siemens star and color patches, whole frames 192, 384 and
49
+ * 768 pixels wide, two runs each; docs/LENS_CATALOGUE.md, "Fast method"): only this lens fell back, 4 of its 8 frames at 192 pixels
50
+ * (f/2.8), 11.6 s each, against 0.17 s for the 10-cell grid.
51
+ */
52
+ export const CATALOGUE_FAST_GRID_FULL_ON_SCREEN =
53
+ /* @__PURE__ */ Object.freeze([Object.freeze({ lensId: "pv-15-2.8-fisheye-pro", fallbacksAtFourCells: Object.freeze({ frames: 8, fellBack: 4, widthPixels: 192 }) })]);
54
+ /** #603: the fewest grid cells for a lens on a fast or an exact request. */
55
+ export function catalogueFastGridSubdivisions(lensId, fast) {
56
+ return fast && !CATALOGUE_FAST_GRID_FULL_ON_SCREEN.some((entry) => entry.lensId === lensId) ? CATALOGUE_FAST_GRID_SPEED_SUBDIVISIONS : CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS;
57
+ }
40
58
  /** Largest move of a node kernel's intensity centroid across one grid cell, in sites (sets finer grids where lateral color moves the PSF). */
41
59
  export const CATALOGUE_FAST_GRID_CENTROID_STEP_SITES = 0.05;
42
60
  /**
@@ -52,7 +70,7 @@ const NEWTON_ITERATIONS = 60;
52
70
  * ⌈Δc / GRID_CENTROID_STEP_SITES⌉) equal cells, Δc the largest centroid move between the interval's two nodes over the other
53
71
  * axis's nodes and the wavelength nodes.
54
72
  */
55
- export function catalogueFastGridAxes(psf) {
73
+ export function catalogueFastGridAxes(psf, minimum = CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS) {
56
74
  const profile = psf.profile, axes = profile.axes, fx = axes.fieldXmm, fy = axes.fieldYmm, wl = axes.wavelengthNm;
57
75
  const centroids = new Map();
58
76
  for (const node of profile.nodes) {
@@ -74,7 +92,7 @@ export function catalogueFastGridAxes(psf) {
74
92
  const a = along ? at(own[i], o, nm) : at(o, own[i], nm), b = along ? at(own[i + 1], o, nm) : at(o, own[i + 1], nm);
75
93
  move = Math.max(move, Math.hypot(a.x - b.x, a.y - b.y));
76
94
  }
77
- const cells = Math.max(CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS, Math.ceil(move / CATALOGUE_FAST_GRID_CENTROID_STEP_SITES - 1e-9));
95
+ const cells = Math.max(minimum, Math.ceil(move / CATALOGUE_FAST_GRID_CENTROID_STEP_SITES - 1e-9));
78
96
  for (let k = 0; k < cells; k++)
79
97
  out.push(own[i] + (own[i + 1] - own[i]) * k / cells);
80
98
  }
@@ -134,7 +152,7 @@ export function createCatalogueLensSignal(given) {
134
152
  return table;
135
153
  };
136
154
  // The field grid, resolved lazily (a region render resolves only the grid points around it).
137
- const axes = catalogueFastGridAxes(psf), gx = axes.x, gy = axes.y, GX = gx.length;
155
+ const axes = catalogueFastGridAxes(psf, input.gridSubdivisions), gx = axes.x, gy = axes.y, GX = gx.length;
138
156
  const tables = new Array(GX * gy.length);
139
157
  let resolved = 0;
140
158
  const tableAt = (i, j) => {
@@ -332,17 +350,17 @@ export function createCatalogueLensSignal(given) {
332
350
  }
333
351
  /** The `raw.expectedSignal` and `fast.lens.catalogue` assumptions of a capture the fast method rendered (kept here, out of the capture bundle's entry). */
334
352
  export function catalogueFastAssumptions(run) {
335
- const tolerance = CATALOGUE_FAST_VERIFICATION_TOLERANCE, cells = CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS, step = CATALOGUE_FAST_GRID_CENTROID_STEP_SITES;
336
- return [{ id: "raw.expectedSignal", value: { method: "tabulated-expected-electrons-catalogue-psf-field-grid", verificationSites: 4, tolerance,
353
+ const tolerance = CATALOGUE_FAST_VERIFICATION_TOLERANCE, cells = run.subdivisions, step = CATALOGUE_FAST_GRID_CENTROID_STEP_SITES;
354
+ return [{ id: "raw.expectedSignal", value: { method: "per-site-integrated-electrons-catalogue-psf-field-grid", verificationSites: 4, tolerance,
337
355
  verificationRelativeDifference: run.verificationRelativeDifference },
338
- explanation: "Each native site's expected photo electrons are tabulated: the sum over the PSF taps of the field factor (vignetting × distortion area factor) times the " +
356
+ explanation: "Each native site's expected photo electrons are integrated per site when the site is read: the sum over the PSF taps of the field factor (vignetting × distortion area factor) times the " +
339
357
  "grid-blended kernel per spectral node times the channel response, integrated with each tap's material spectrum (see fast.lens.catalogue). The sensor stage (dark charge, Poisson draws, read noise, ADC) " +
340
358
  "is the native one with each site's own seeds. One site of each CFA phase ran the exact chain (the environment PSF quadrature): its readout was reproduced bit for bit and " +
341
359
  "its electrons agreed with the fast ones within the tolerance (verificationRelativeDifference: the largest difference there)." },
342
360
  { id: "fast.lens.catalogue", value: { method: "field-grid-bilinear-psf", gridColumns: run.columns, gridRows: run.rows, gridPointsResolved: run.resolved,
343
361
  minimumSubdivisions: cells, centroidStepSites: step, verificationTolerance: tolerance },
344
362
  explanation: "Fast method (#568), an approximation of the exact one: the catalogue PSF is resolved exactly on a field grid (each interval between the profile's field nodes " +
345
- "split into at least " + cells + " cells, more where the node kernels' centroids move by over " + step + " site per cell), and each site takes the bilinear blend of its " +
363
+ "split into at least " + cells + " cells (#603: " + CATALOGUE_FAST_GRID_SPEED_SUBDIVISIONS + " on a fast request, " + CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS + " on an exact one and for the lenses of CATALOGUE_FAST_GRID_FULL_ON_SCREEN), more where the node kernels' centroids move by over " + step + " site per cell), and each site takes the bilinear blend of its " +
346
364
  "four grid points' kernels instead of its own. Its error is at most the kernels' L1 difference times the brightest tap's signal; docs/LENS_CATALOGUE.md (\"Fast method\") " +
347
365
  "records it measured against the exact method. Distortion, vignetting and projection are the exact method's (the radial inverse by Newton's method, equal to rounding)." }];
348
366
  }
@@ -1 +1 @@
1
- {"version":3,"file":"catalogue-lens-signal.js","sourceRoot":"","sources":["../../src/facade/catalogue-lens-signal.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,uBAAuB,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AACrG,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,uCAAuC,EAAsC,MAAM,sCAAsC,CAAC;AACnI,OAAO,EAAE,cAAc,EAAE,2BAA2B,EAAmC,MAAM,+BAA+B,CAAC;AAG7H,0IAA0I;AAC1I,MAAM,CAAC,MAAM,wCAAwC,GAAG,EAAE,CAAC;AAC3D,8IAA8I;AAC9I,MAAM,CAAC,MAAM,uCAAuC,GAAG,IAAI,CAAC;AAC5D;;;GAGG;AACH,MAAM,CAAC,MAAM,qCAAqC,GAAG,KAAK,CAAC;AAC3D,6FAA6F;AAC7F,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,CAAC;AAC7B,MAAM,iBAAiB,GAAG,EAAE,CAAC;AA0C7B;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAoC;IACxE,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC;IACjH,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoC,CAAC;IAC9D,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC;QAC1B,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,GAAG,GAAG,GAAG,CAAC,CAAC,QAAQ,GAAG,GAAG,GAAG,CAAC,CAAC,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACnG,CAAC;IACD,MAAM,EAAE,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,EAAU,EAA4B,EAAE;QACxE,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,yBAAyB,CAAC,0DAA0D,CAAC,CAAC;QACxG,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,CAAC,GAAsB,EAAE,KAAwB,EAAE,KAAc,EAAY,EAAE;QAC1F,MAAM,GAAG,GAAa,EAAE,CAAC;QACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,IAAI,IAAI,GAAG,CAAC,CAAC;YACb,KAAK,MAAM,CAAC,IAAI,KAAK;gBAAE,KAAK,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;oBAC3C,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;oBACvH,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC1D,CAAC;YACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,wCAAwC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,uCAAuC,GAAG,IAAI,CAAC,CAAC,CAAC;YACnI,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE;gBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAE,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAE,GAAG,GAAG,CAAC,CAAC,CAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;QAC1F,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,CAAC;QAC/B,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IACF,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC;AAC3D,CAAC;AAED,4GAA4G;AAC5G,SAAS,MAAM,CAAC,IAAuB,EAAE,CAAS;IAChD,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IACjC,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC;QAAC,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;QAAC,IAAI,IAAI,CAAC,GAAG,CAAE,IAAI,CAAC;YAAE,EAAE,GAAG,GAAG,CAAC;;YAAM,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;IAAC,CAAC;IACrG,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAE,GAAG,IAAI,CAAC,EAAE,CAAE,CAAC,CAAC;IACxD,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACnD,CAAC;AAOD,IAAI,QAAiD,CAAC;AACtD,MAAM,UAAU,8BAA8B,CAAC,IAA6C,IAAU,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC;AAExH,kEAAkE;AAClE,MAAM,UAAU,yBAAyB,CAAC,KAA+B;IACvE,QAAQ,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;IAC3B,MAAM,KAAK,GAAG,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAChF,MAAM,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,oBAAoB,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IACjH,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC;IACnE,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,yBAAyB,CAAC,oDAAoD,CAAC,CAAC;IACtG,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC;IACxJ,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK;QAAE,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,KAAK,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,KAAK,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,KAAK,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,KAAK,EAAE;YACnL,MAAM,IAAI,yBAAyB,CAAC,gEAAgE,CAAC,CAAC;IACxG,8GAA8G;IAC9G,MAAM,SAAS,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,EAAE,UAAU,GAAG,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,SAAS,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;IACtF,iIAAiI;IACjI,+HAA+H;IAC/H,MAAM,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC;IACjC,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC5J,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;IACnC,+HAA+H;IAC/H,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAE,QAAgB,EAAgB,EAAE;QACvE,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC;QAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,2BAA2B,CAAC,EAAE,GAAG,GAAG,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC,CAAE,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,mBAAmB,CAAC;YACxJ,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI;gBAAE,MAAM,IAAI,yBAAyB,CAAC,yDAAyD,CAAC,CAAC;YAC3H,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAE,CAAC;gBACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE;oBAAE,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;YACpF,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IACF,6FAA6F;IAC7F,MAAM,IAAI,GAAG,qBAAqB,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC;IAClF,MAAM,MAAM,GAAiC,IAAI,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;IACvE,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,MAAM,OAAO,GAAG,CAAC,CAAS,EAAE,CAAS,EAAgB,EAAE;QACrD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACrB,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,CAAC,EAAE,CAAC;YAAC,CAAC,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC,CAAE,CAAC,CAAC;YAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAAC,QAAQ,EAAE,CAAC;QAAC,CAAC;QACvE,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;IACF,2GAA2G;IAC3G,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC;IACzH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;QAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IACtH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;QAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAEvH,sHAAsH;IACtH,MAAM,EAAE,GAAG,2BAA2B,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC,oBAAoB,CAAC;IACvG,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,kBAAkB,CAAC;IAC9D,MAAM,YAAY,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,uCAAuC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9G,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,EAAE,WAAW,GAAG,KAAK,CAAC,UAAU,KAAK,aAAa,CAAC;IACtF,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC3B,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,GAAW,EAAQ,EAAE;QAC7C,MAAM,MAAM,GAAG,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,CAAC;QAClC,IAAI,MAAM,GAAG,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,GAAG,CAAC,CAAC;QAC/C,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,UAAU,CAAC,YAAY,EAAE,IAAI,GAAG,UAAU,CAAC,qBAAqB,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;YAChI,IAAI,GAAG,GAAG,EAAE,CAAC;YACb,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;gBACX,gGAAgG;gBAChG,IAAI,SAAS,GAAG,KAAK,CAAC;gBACtB,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,iBAAiB,EAAE,EAAE,EAAE,EAAE,CAAC;oBAC9C,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,EAAE,KAAK,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,KAAK,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;oBAC9J,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;wBAAE,MAAM;oBACxB,MAAM,IAAI,GAAG,KAAK,GAAG,KAAK,CAAC;oBAC3B,GAAG,IAAI,IAAI,CAAC;oBACZ,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC;wBAAC,SAAS,GAAG,IAAI,CAAC;wBAAC,MAAM;oBAAC,CAAC;gBAC9E,CAAC;gBACD,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;oBAAE,MAAM,IAAI,yBAAyB,CAAC,+DAA+D,CAAC,CAAC;YACrI,CAAC;YACD,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,UAAU,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;YAClJ,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;gBAAC,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC;gBAAC,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC;YAAC,CAAC;YACzD,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC;YAC5B,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,MAAM,IAAI,yBAAyB,CAAC,gFAAgF,CAAC,CAAC;QACnK,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QAClF,IAAI,WAAW,EAAE,CAAC;YAAC,EAAE,GAAG,MAAM,GAAG,EAAE,GAAG,UAAU,CAAC;YAAC,EAAE,GAAG,MAAM,GAAG,EAAE,GAAG,UAAU,CAAC;YAAC,EAAE,GAAG,MAAM,CAAC;YAAC,OAAO;QAAC,CAAC;QACvG,IAAI,KAAK,CAAC,6BAA6B,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;YAAC,EAAE,GAAG,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAC1I,MAAM,CAAC,GAAG,4BAA4B,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7E,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAAC,EAAE,GAAG,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QACnC,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,kBAAkB,CAAC;QAAC,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,kBAAkB,CAAC;QAAC,EAAE,GAAG,MAAM,CAAC;IAC5I,CAAC,CAAC;IACF,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACnB,iHAAiH;IACjH,MAAM,OAAO,GAAG,CAAC,CAAS,EAAE,CAAS,EAAQ,EAAE;QAC7C,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,EAAE,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;QAClE,EAAE,GAAG,EAAE,CAAC;QACR,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;YAAC,EAAE,GAAG,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QACjC,MAAM,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACnC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;YAAE,MAAM,IAAI,yBAAyB,CAAC,yBAAyB,CAAC,CAAC;QAC/G,EAAE,GAAG,CAAC,CAAC;QAAC,OAAO,EAAE,CAAC;IACpB,CAAC,CAAC;IACF,kEAAkE;IAClE,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,WAAW,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,SAAS,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC;IACvG,MAAM,MAAM,GAAG,CAAC,EAAU,EAAE,EAAU,EAAE,EAAU,EAAE,EAAU,EAAQ,EAAE;QACtE,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,SAAS,GAAG,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,OAAO,GAAG,SAAS,CAAC;QAC9E,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,YAAY,EAAE,CAAC;YAAC,EAAE,GAAG,CAAC,CAAC;YAAC,EAAE,GAAG,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAC1E,GAAG,GAAG,EAAE,GAAG,SAAS,CAAC;QAAC,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC;QAAC,EAAE,GAAG,CAAC,CAAC;QAAC,EAAE,GAAG,CAAC,CAAC;QACzD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAAC,WAAW,GAAG,IAAI,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAAC,SAAS,GAAG,IAAI,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAAC,CAAC;QAC7G,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAAC,OAAO,CAAC,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;gBAAC,WAAW,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;gBAAC,SAAS,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YAAC,CAAC;IAChJ,CAAC,CAAC;IACF,gIAAgI;IAChI,4HAA4H;IAC5H,MAAM,SAAS,GAAmB,EAAE,EAAE,KAAK,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,CAAS,EAAgB,EAAE;QACtD,IAAI,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK;YAAE,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC;QAC/D,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YACnB,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,GAAG,OAAO,CAAC,CAAC,CAAE,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YAChF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE;gBAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;YAC7E,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE;QAC5C,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1B,IAAI,EAAgB,EAAE,EAAgB,EAAE,EAAU,CAAC;QACnD,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YAAC,EAAE,GAAG,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;YAAC,EAAE,GAAG,CAAC,CAAC;QAAC,CAAC;aACpH,CAAC;YAAC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;YAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;YAAC,EAAE,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC;QAAC,CAAC;QAC7F,MAAM,MAAM,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,SAAS,IAAI,GAAG,IAAI,CAAC,GAAG,OAAO,IAAI,GAAG,IAAI,CAAC,GAAG,UAAU,GAAG,GAAG,GAAG,EAAE,IAAI,CAAC,GAAG,SAAS,GAAG,GAAG,GAAG,EAAE,CAAC;QAC7H,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;QACrC,+HAA+H;QAC/H,+CAA+C;QAC/C,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QACnB,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;YACtC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;YACtB,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBACpC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;gBACtB,IAAI,CAAS,EAAE,CAAS,CAAC;gBACzB,IAAI,MAAM,EAAE,CAAC;oBAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC;oBAAC,CAAC,GAAG,WAAW,CAAC,EAAE,CAAE,CAAC;oBAAC,CAAC,GAAG,SAAS,CAAC,EAAE,CAAE,CAAC;gBAAC,CAAC;qBAAM,CAAC;oBAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;oBAAC,CAAC,GAAG,EAAE,CAAC;oBAAC,CAAC,GAAG,EAAE,CAAC;gBAAC,CAAC;gBACtI,IAAI,CAAC,KAAK,CAAC;oBAAE,SAAS;gBACtB,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAE,EAAE,EAAE,GAAG,WAAW,GAAG,CAAC,GAAG,KAAK,CAAC;gBACpD,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;gBACnB,IAAI,EAAE,KAAK,CAAC;oBAAE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE;wBAAE,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAE,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;;oBACnE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;wBAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;wBAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAE,GAAG,CAAC,CAAC;wBAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAE,GAAG,CAAC,CAAC;oBAAC,CAAC;gBACvG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;gBAAC,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;YAC7B,CAAC;QACH,CAAC;QACD,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IACjD,CAAC,CAAC;IACF,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,IAAI,OAAO,KAAa,OAAO,OAAO,CAAC,CAAC,CAAC;QACzC,IAAI,IAAI,KAA0D,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;KACvH,CAAC;AACJ,CAAC;AAED,2JAA2J;AAC3J,MAAM,UAAU,wBAAwB,CAAC,GAAgG;IAEvI,MAAM,SAAS,GAAG,qCAAqC,EAAE,KAAK,GAAG,wCAAwC,EAAE,IAAI,GAAG,uCAAuC,CAAC;IAC1J,OAAO,CAAC,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,uDAAuD,EAAE,iBAAiB,EAAE,CAAC,EAAE,SAAS;gBAC3I,8BAA8B,EAAE,GAAG,CAAC,8BAA8B,EAAE;YACtE,WAAW,EAAE,2JAA2J;gBACtK,2MAA2M;gBAC3M,4KAA4K;gBAC5K,8HAA8H,EAAE;QAClI,EAAE,EAAE,EAAE,qBAAqB,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,yBAAyB,EAAE,WAAW,EAAE,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,kBAAkB,EAAE,GAAG,CAAC,QAAQ;gBACrJ,mBAAmB,EAAE,KAAK,EAAE,iBAAiB,EAAE,IAAI,EAAE,qBAAqB,EAAE,SAAS,EAAE;YACzF,WAAW,EAAE,gKAAgK;gBAC3K,sBAAsB,GAAG,KAAK,GAAG,8DAA8D,GAAG,IAAI,GAAG,iEAAiE;gBAC1K,2KAA2K;gBAC3K,wKAAwK,EAAE,CAAC,CAAC;AAChL,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * #568: the fast method of `simulateCapture`'s `lens.catalogue` (requested with `fast: true` or `lens.catalogue.fast`): each\n * native site's expected photo electrons from tables instead of the environment PSF quadrature's per-tap scene queries.\n * Loaded on demand with the catalogue (`generic-lens-capture.ts`), so a capture without a catalogue lens never loads it.\n *\n * What the exact method computes. The environment PSF quadrature forms, for site q of CFA channel c,\n * μ_c(q) = Σ_λ A_c(λ) Σ_k K_{q,λ}(k)·F(s_k)·L(D(s_k), λ), s_k = q + (c_x − k_x, k_y − c_y)·p,\n * with K_{q,λ} the catalogue PSF resolved at the site's own field point (`resolveLensSampledPsfKernel`: the profile's 5 × 5 field\n * nodes × 5 wavelength nodes interpolated with centroid alignment; row index k_y increases with image +Y, `sensorPsfSourcePoint`),\n * F = T·A the field factor at the tap point (vignetting throughput × distortion area factor), D the scene ray (inverse radial\n * distortion, then the rectilinear or equisolid projection at the thin-lens image distance) and A_c(λ) the electrons per unit\n * spectral radiance on the axis (the tabulated path's channel response). Every tap of a site-centre query is a lattice point.\n *\n * The approximation (the only one). Resolving K_{q,λ} at every site and spectral node is what makes the exact method slow, so the\n * fast method resolves it exactly on a field grid and blends it bilinearly between the four grid points around each site:\n * K̃_{q,λ} = Σ_g b_g(q)·K_{g,λ}.\n * The grid subdivides each interval between the profile's field nodes into at least GRID_MINIMUM_SUBDIVISIONS cells, and into\n * more where the node kernels' intensity centroids move by more than GRID_CENTROID_STEP_SITES sites across the interval (lateral\n * colour moves the PSF across the frame; a blend of two shifted kernels is not the shifted kernel). Since the blend is linear,\n * the channel response folds into the grid kernels once per grid point and node, and each tap's signal is integrated from its\n * material's spectrum when the site is read (2.21.0; no material is folded into a kernel):\n * μ̃_c(q) = Σ_k F(s_k)·Σ_λ L_{m(s_k)}(λ)·Σ_g b_g(q)·C_{g,c}(k, λ), C_{g,c}(k, λ) = A_c(λ)·K_{g,λ}(k),\n * the blend taken along y once per grid column and native row, so a site costs (2R + 1)² taps of N nodes each instead of\n * (2R + 1)² scene queries per spectral node. Its error against the exact method is\n * bounded by ‖K̃ − K‖₁ times the brightest tap's signal; tests measure both (test/simulate-capture-lens-catalogue-fast.test.ts).\n *\n * The scene points. The mapping is the environment's (`undistortedImagePoint`, `lensProjectionDirectionValue`, the planar\n * provider's plane point), with the radial inverse solved by Newton's method instead of bisection: both converge to the same\n * root to rounding. Outside a circular fisheye's image circle (`outsideImageCircle: \"backward-ray\"`) and beyond the horizon the\n * scene radiance is zero, as in the capture.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { insideRadialImageCircle, lensProjectionDirectionValue } from \"../camera/lens-projection.js\";\nimport { resolveProjectionDistanceMm } from \"../motion/camera-rotation.js\";\nimport { prepareIlluminationVignettingThroughput, type IlluminationVignettingProfile } from \"../optics/illumination-vignetting.js\";\nimport { kernelCentroid, resolveLensSampledPsfKernel, type ResolveLensSampledPsfInput } from \"../optics/lens-psf-profile.js\";\nimport type { DisplayViewScene } from \"./expected-signal.js\";\n\n/** Fewest grid cells between neighboring profile field nodes (10 since #589: with 4, 0.4 % of quick frames failed the run-time check). */\nexport const CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS = 10;\n/** Largest move of a node kernel's intensity centroid across one grid cell, in sites (sets finer grids where lateral color moves the PSF). */\nexport const CATALOGUE_FAST_GRID_CENTROID_STEP_SITES = 0.05;\n/**\n * Largest relative difference between the fast and the exact expected electrons that the run-time verification (one site per\n * CFA phase through the exact chain, `renderTabulatedNativeRaw`) accepts; above it the capture runs the exact method.\n */\nexport const CATALOGUE_FAST_VERIFICATION_TOLERANCE = 0.005;\n/** Largest cache window, in lattice points; a larger window is evaluated without caching. */\nconst WINDOW_LIMIT = 1 << 22;\nconst NEWTON_ITERATIONS = 60;\n\nexport interface CatalogueLensSignalInput {\n nativeWidth: number;\n nativeHeight: number;\n /** Site pitch, µm. */\n pitch: number;\n /** The catalogue PSF's optical state (profile, focal length, focus, f-number, defocus), as the site inputs' `psf.configuration.psf`. */\n psf: Omit<ResolveLensSampledPsfInput, \"fieldPointMm\" | \"wavelengthNm\">;\n /** Spectral nodes and, per CFA channel (red, green, blue), the expected electrons per unit spectral radiance at each node. */\n wavelengthsNm: readonly number[];\n electronsPerRadiance: readonly [Float64Array, Float64Array, Float64Array];\n /** The scene's chart materials (the tabulated path's material tables). */\n scene: Extract<DisplayViewScene, { kind: \"materials\" }>;\n /** CFA channel index (0 red, 1 green, 2 blue) of native site (x, y). */\n channelAt(x: number, y: number): number;\n /** The radial distortion profile (r_d = r·(1 + k1ρ² + k2ρ⁴ + k3ρ⁶), ρ = r / normalizationRadiusMm); absent without distortion. */\n distortion?: { normalizationRadiusMm: number; coefficients: { k1: number; k2: number; k3: number } };\n vignetting?: IlluminationVignettingProfile;\n projection: \"rectilinear\" | \"fisheye-equisolid-angle\";\n /** True for a catalogue fisheye: a sensor point outside the image circle looks straight back and sees no scene. */\n outsideImageCircleSeesNothing: boolean;\n focalLengthMm: number;\n focusDistanceM: number;\n /** The planar provider's plane distance and frame-unit scale. */\n distanceM: number;\n metresPerFrameUnit: number;\n /** Internal test hook: resolve every site's kernels exactly (the exact method's sum, slowly) instead of blending the grid. */\n exactKernels?: boolean;\n}\n\nexport interface CatalogueLensSignal {\n /** Starts a cache window of native sites [x0, x1) × [y0, y1) (see `DisplayViewExpectedSignal.window`). */\n window(x0: number, y0: number, x1: number, y1: number): void;\n /** Expected photo electrons of native site (x, y) for its own CFA channel. */\n site(x: number, y: number): number;\n /** Scene material lookups so far. */\n readonly lookups: number;\n /** Grid points per axis (columns, rows) and how many were resolved so far. */\n readonly grid: { columns: number; rows: number; resolved: number };\n}\n\n/**\n * The grid axes: each interval between neighboring profile field nodes split into max(GRID_MINIMUM_SUBDIVISIONS,\n * ⌈Δc / GRID_CENTROID_STEP_SITES⌉) equal cells, Δc the largest centroid move between the interval's two nodes over the other\n * axis's nodes and the wavelength nodes.\n */\nexport function catalogueFastGridAxes(psf: CatalogueLensSignalInput[\"psf\"]): { x: number[]; y: number[] } {\n const profile = psf.profile, axes = profile.axes, fx = axes.fieldXmm, fy = axes.fieldYmm, wl = axes.wavelengthNm;\n const centroids = new Map<string, { x: number; y: number }>();\n for (const node of profile.nodes) {\n const c = node.coordinate;\n centroids.set(c.fieldXmm + \":\" + c.fieldYmm + \":\" + c.wavelengthNm, kernelCentroid(node.kernel));\n }\n const at = (x: number, y: number, nm: number): { x: number; y: number } => {\n const c = centroids.get(x + \":\" + y + \":\" + nm);\n if (!c) throw new InvalidConfigurationError(\"lens.catalogue fast: the PSF profile lacks a field node.\");\n return c;\n };\n const axis = (own: readonly number[], other: readonly number[], along: boolean): number[] => {\n const out: number[] = [];\n for (let i = 0; i + 1 < own.length; i++) {\n let move = 0;\n for (const o of other) for (const nm of wl) {\n const a = along ? at(own[i]!, o, nm) : at(o, own[i]!, nm), b = along ? at(own[i + 1]!, o, nm) : at(o, own[i + 1]!, nm);\n move = Math.max(move, Math.hypot(a.x - b.x, a.y - b.y));\n }\n const cells = Math.max(CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS, Math.ceil(move / CATALOGUE_FAST_GRID_CENTROID_STEP_SITES - 1e-9));\n for (let k = 0; k < cells; k++) out.push(own[i]! + (own[i + 1]! - own[i]!) * k / cells);\n }\n out.push(own[own.length - 1]!);\n return out;\n };\n return { x: axis(fx, fy, true), y: axis(fy, fx, false) };\n}\n\n/** The cell [i, i + 1] of an ascending axis holding v (clamped to the ends) and v's weight toward i + 1. */\nfunction cellOf(axis: readonly number[], v: number): { i: number; f: number } {\n let lo = 0, hi = axis.length - 2;\n while (lo < hi) { const mid = (lo + hi + 1) >> 1; if (axis[mid]! <= v) lo = mid; else hi = mid - 1; }\n const f = (v - axis[lo]!) / (axis[lo + 1]! - axis[lo]!);\n return { i: lo, f: Math.min(1, Math.max(0, f)) };\n}\n\n/**\n * Internal test hook (never set by the engine): `exactKernels` makes the facade's signals resolve every site's kernels exactly;\n * `onInput` receives each input the facade builds, so a test can compare the grid blend with the exact sum site by site.\n */\nexport interface CatalogueLensSignalTestHook { exactKernels?: boolean; onInput?(input: CatalogueLensSignalInput): void }\nlet testHook: CatalogueLensSignalTestHook | undefined;\nexport function setCatalogueLensSignalTestHook(hook: CatalogueLensSignalTestHook | undefined): void { testHook = hook; }\n\n/** The fast method's expected signal (see the module comment). */\nexport function createCatalogueLensSignal(given: CatalogueLensSignalInput): CatalogueLensSignal {\n testHook?.onInput?.(given);\n const input = testHook?.exactKernels ? { ...given, exactKernels: true } : given;\n const { nativeWidth: W, nativeHeight: H, psf, wavelengthsNm, electronsPerRadiance: A, scene, channelAt } = input;\n const mmPerSite = input.pitch / 1000, nodes = wavelengthsNm.length;\n const first = psf.profile.nodes[0];\n if (!first) throw new InvalidConfigurationError(\"lens.catalogue fast: the PSF profile has no nodes.\");\n const kw = first.kernel.widthSamples, kh = first.kernel.heightSamples, cx = first.kernel.centerSampleX, cy = first.kernel.centerSampleY, taps = kw * kh;\n for (const node of psf.profile.nodes) if (node.kernel.widthSamples !== kw || node.kernel.heightSamples !== kh || node.kernel.centerSampleX !== cx || node.kernel.centerSampleY !== cy)\n throw new InvalidConfigurationError(\"lens.catalogue fast: the PSF profile's kernels differ in size.\");\n // Lattice reach of the taps around a site: x from −cx … kw − 1 − cx (as c_x − k_x), y from −cy … kh − 1 − cy.\n const reachLeft = kw - 1 - cx, reachRight = cx, reachUp = cy, reachDown = kh - 1 - cy;\n // Each material's spectral radiance at the nodes (a neutral one: its reflectance times the white radiance). Only the spectra are\n // kept: a site's signal is integrated from its taps' material spectra when it is read, so no material is folded into a kernel.\n const M = scene.materials.length;\n const spectra = scene.materials.map((m) => (\"neutral\" in m ? Float64Array.from(scene.whiteRadiance, (w) => m.neutral * w) : Float64Array.from(m.radiance)));\n const tableSize = 3 * taps * nodes;\n // A_c(λ_n)·K_n(k) for the kernels of one field point, at ((c·taps + k)·nodes + n): the channel response per node, no material.\n const foldKernels = (fieldXmm: number, fieldYmm: number): Float64Array => {\n const table = new Float64Array(tableSize);\n for (let n = 0; n < nodes; n++) {\n const kernel = resolveLensSampledPsfKernel({ ...psf, wavelengthNm: wavelengthsNm[n]!, fieldPointMm: { x: fieldXmm, y: fieldYmm } }).normalizedIntensity;\n if (kernel.length !== taps) throw new InvalidConfigurationError(\"lens.catalogue fast: a resolved kernel differs in size.\");\n for (let c = 0; c < 3; c++) {\n const a = A[c]![n]!;\n for (let k = 0; k < taps; k++) table[(c * taps + k) * nodes + n] = a * kernel[k]!;\n }\n }\n return table;\n };\n // The field grid, resolved lazily (a region render resolves only the grid points around it).\n const axes = catalogueFastGridAxes(psf), gx = axes.x, gy = axes.y, GX = gx.length;\n const tables: (Float64Array | undefined)[] = new Array(GX * gy.length);\n let resolved = 0;\n const tableAt = (i: number, j: number): Float64Array => {\n const k = j * GX + i;\n let t = tables[k];\n if (!t) { t = foldKernels(gx[i]!, gy[j]!); tables[k] = t; resolved++; }\n return t;\n };\n // Each native column's and row's grid cell and blend weight (field +Y up: row y sits at −(y + ½ − H/2)·p).\n const cellX = new Int32Array(W), weightX = new Float64Array(W), cellY = new Int32Array(H), weightY = new Float64Array(H);\n for (let x = 0; x < W; x++) { const c = cellOf(gx, (x + 0.5 - W / 2) * mmPerSite); cellX[x] = c.i; weightX[x] = c.f; }\n for (let y = 0; y < H; y++) { const c = cellOf(gy, -(y + 0.5 - H / 2) * mmPerSite); cellY[y] = c.i; weightY[y] = c.f; }\n\n // The scene point and field factor of a native sensor point (mm, +Y down); factor 0 where the scene radiance is zero.\n const pd = resolveProjectionDistanceMm(input.focalLengthMm, input.focusDistanceM).projectionDistanceMm;\n const planeScale = input.distanceM / input.metresPerFrameUnit;\n const throughputAt = input.vignetting ? prepareIlluminationVignettingThroughput(input.vignetting) : undefined;\n const distortion = input.distortion, rectilinear = input.projection === \"rectilinear\";\n let mu = 0, mv = 0, mf = 0;\n const map = (xMm: number, yMm: number): void => {\n const imageX = xMm, imageY = -yMm;\n let idealX = imageX, idealY = imageY, area = 1;\n if (distortion) {\n const { k1, k2, k3 } = distortion.coefficients, norm = distortion.normalizationRadiusMm, rd = Math.hypot(imageX, imageY) / norm;\n let rho = rd;\n if (rd > 0) {\n // Newton's method on ρ·s(ρ) = ρ_d (monotonic over the profile's validated range), from ρ = ρ_d.\n let converged = false;\n for (let it = 0; it < NEWTON_ITERATIONS; it++) {\n const r2 = rho * rho, value = rho * (1 + k1 * r2 + k2 * r2 * r2 + k3 * r2 * r2 * r2) - rd, slope = 1 + 3 * k1 * r2 + 5 * k2 * r2 * r2 + 7 * k3 * r2 * r2 * r2;\n if (!(slope > 0)) break;\n const step = value / slope;\n rho -= step;\n if (Math.abs(step) <= 4 * Number.EPSILON * rho) { converged = true; break; }\n }\n if (!converged || !(rho > 0)) throw new InvalidConfigurationError(\"lens.catalogue fast: the inverse distortion did not converge.\");\n }\n const r2 = rho * rho, s = 1 + k1 * r2 + k2 * r2 * r2 + k3 * r2 * r2 * r2, derivative = 1 + 3 * k1 * r2 + 5 * k2 * r2 * r2 + 7 * k3 * r2 * r2 * r2;\n if (rd > 0) { idealX = imageX / s; idealY = imageY / s; }\n area = 1 / (s * derivative);\n if (!(area > 0) || !Number.isFinite(area)) throw new InvalidConfigurationError(\"lens.catalogue fast: the distortion area factor must stay finite and positive.\");\n }\n const factor = (throughputAt ? throughputAt({ x: imageX, y: imageY }) : 1) * area;\n if (rectilinear) { mu = idealX / pd * planeScale; mv = idealY / pd * planeScale; mf = factor; return; }\n if (input.outsideImageCircleSeesNothing && !insideRadialImageCircle(input.projection, pd, Math.hypot(idealX, idealY))) { mf = 0; return; }\n const d = lensProjectionDirectionValue(input.projection, pd, idealX, idealY);\n if (!(d.z > 0)) { mf = 0; return; }\n mu = d.x * (input.distanceM / d.z) / input.metresPerFrameUnit; mv = d.y * (input.distanceM / d.z) / input.metresPerFrameUnit; mf = factor;\n };\n let lookups = 0;\n let lm = 0, lf = 0;\n /** The material and field factor of lattice point (p, q) (sites from the top-left site, the lattice formula). */\n const lattice = (p: number, q: number): void => {\n map((p + 0.5 - W / 2) * mmPerSite, (q + 0.5 - H / 2) * mmPerSite);\n lf = mf;\n if (mf === 0) { lm = 0; return; }\n const m = scene.materialAt(mu, mv);\n if (!(m >= 0 && m < M) || !Number.isInteger(m)) throw new InvalidConfigurationError(\"Unknown chart material.\");\n lm = m; lookups++;\n };\n // The window's lattice: points [wx0, wx0 + ww) × [wy0, wy0 + wh).\n let wx0 = 0, wy0 = 0, ww = 0, wh = 0, winMaterial = new Int32Array(0), winFactor = new Float64Array(0);\n const window = (x0: number, y0: number, x1: number, y1: number): void => {\n const w = x1 - x0 + reachLeft + reachRight, h = y1 - y0 + reachUp + reachDown;\n if (!(w > 0 && h > 0) || w * h > WINDOW_LIMIT) { ww = 0; wh = 0; return; }\n wx0 = x0 - reachLeft; wy0 = y0 - reachUp; ww = w; wh = h;\n if (winMaterial.length < w * h) { winMaterial = new Int32Array(w * h); winFactor = new Float64Array(w * h); }\n for (let q = 0; q < h; q++) for (let p = 0; p < w; p++) { lattice(wx0 + p, wy0 + q); winMaterial[q * w + p] = lm; winFactor[q * w + p] = lf; }\n };\n // A site's kernel is the bilinear blend of its cell's four grid kernels. Blended along y first, once per grid column and native\n // row (every site of a row has the same fy): R_i(y) = (1 − fy)·T(i, j) + fy·T(i, j + 1), kept for the row the sites are on.\n const rowTables: Float64Array[] = [], rowOf = new Int32Array(GX).fill(-1);\n const rowTable = (i: number, y: number): Float64Array => {\n let table = rowTables[i];\n if (!table) table = rowTables[i] = new Float64Array(tableSize);\n if (rowOf[i] !== y) {\n const j = cellY[y]!, fy = weightY[y]!, a = tableAt(i, j), b = tableAt(i, j + 1);\n for (let e = 0; e < tableSize; e++) table[e] = (1 - fy) * a[e]! + fy * b[e]!;\n rowOf[i] = y;\n }\n return table;\n };\n const site = (x: number, y: number): number => {\n const c = channelAt(x, y);\n let r0: Float64Array, r1: Float64Array, fx: number;\n if (input.exactKernels) { r0 = r1 = foldKernels((x + 0.5 - W / 2) * mmPerSite, -(y + 0.5 - H / 2) * mmPerSite); fx = 0; }\n else { const i = cellX[x]!; r0 = rowTable(i, y); r1 = rowTable(i + 1, y); fx = weightX[x]!; }\n const inside = ww > 0 && x - reachLeft >= wx0 && y - reachUp >= wy0 && x + reachRight < wx0 + ww && y + reachDown < wy0 + wh;\n const channelBase = c * taps * nodes;\n // Each tap's signal is integrated from its material's spectrum against the two row-blended kernels per node; the blend along x\n // is linear, so it is applied to the two sums.\n let s0 = 0, s1 = 0;\n for (let ky = 0, k = 0; ky < kh; ky++) {\n const q = y + ky - cy;\n for (let kx = 0; kx < kw; kx++, k++) {\n const p = x + cx - kx;\n let m: number, f: number;\n if (inside) { const at = (q - wy0) * ww + p - wx0; m = winMaterial[at]!; f = winFactor[at]!; } else { lattice(p, q); m = lm; f = lf; }\n if (f === 0) continue;\n const L = spectra[m]!, at = channelBase + k * nodes;\n let w0 = 0, w1 = 0;\n if (fx === 0) for (let n = 0; n < nodes; n++) w0 += r0[at + n]! * L[n]!;\n else for (let n = 0; n < nodes; n++) { const l = L[n]!; w0 += r0[at + n]! * l; w1 += r1[at + n]! * l; }\n s0 += f * w0; s1 += f * w1;\n }\n }\n return fx === 0 ? s0 : (1 - fx) * s0 + fx * s1;\n };\n return {\n window, site,\n get lookups(): number { return lookups; },\n get grid(): { columns: number; rows: number; resolved: number } { return { columns: GX, rows: gy.length, resolved }; }\n };\n}\n\n/** The `raw.expectedSignal` and `fast.lens.catalogue` assumptions of a capture the fast method rendered (kept here, out of the capture bundle's entry). */\nexport function catalogueFastAssumptions(run: { columns: number; rows: number; resolved: number; verificationRelativeDifference: number }):\n { id: string; value: Record<string, unknown>; explanation: string }[] {\n const tolerance = CATALOGUE_FAST_VERIFICATION_TOLERANCE, cells = CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS, step = CATALOGUE_FAST_GRID_CENTROID_STEP_SITES;\n return [{ id: \"raw.expectedSignal\", value: { method: \"tabulated-expected-electrons-catalogue-psf-field-grid\", verificationSites: 4, tolerance,\n verificationRelativeDifference: run.verificationRelativeDifference },\n explanation: \"Each native site's expected photo electrons are tabulated: the sum over the PSF taps of the field factor (vignetting × distortion area factor) times the \" +\n \"grid-blended kernel per spectral node times the channel response, integrated with each tap's material spectrum (see fast.lens.catalogue). The sensor stage (dark charge, Poisson draws, read noise, ADC) \" +\n \"is the native one with each site's own seeds. One site of each CFA phase ran the exact chain (the environment PSF quadrature): its readout was reproduced bit for bit and \" +\n \"its electrons agreed with the fast ones within the tolerance (verificationRelativeDifference: the largest difference there).\" },\n { id: \"fast.lens.catalogue\", value: { method: \"field-grid-bilinear-psf\", gridColumns: run.columns, gridRows: run.rows, gridPointsResolved: run.resolved,\n minimumSubdivisions: cells, centroidStepSites: step, verificationTolerance: tolerance },\n explanation: \"Fast method (#568), an approximation of the exact one: the catalogue PSF is resolved exactly on a field grid (each interval between the profile's field nodes \" +\n \"split into at least \" + cells + \" cells, more where the node kernels' centroids move by over \" + step + \" site per cell), and each site takes the bilinear blend of its \" +\n \"four grid points' kernels instead of its own. Its error is at most the kernels' L1 difference times the brightest tap's signal; docs/LENS_CATALOGUE.md (\\\"Fast method\\\") \" +\n \"records it measured against the exact method. Distortion, vignetting and projection are the exact method's (the radial inverse by Newton's method, equal to rounding).\" }];\n}\n"]}
1
+ {"version":3,"file":"catalogue-lens-signal.js","sourceRoot":"","sources":["../../src/facade/catalogue-lens-signal.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * #568: the fast method of `simulateCapture`'s `lens.catalogue` (requested with `fast: true` or `lens.catalogue.fast`): each\n * native site's expected photo electrons from tables instead of the environment PSF quadrature's per-tap scene queries.\n * Loaded on demand with the catalogue (`generic-lens-capture.ts`), so a capture without a catalogue lens never loads it.\n *\n * What the exact method computes. The environment PSF quadrature forms, for site q of CFA channel c,\n * μ_c(q) = Σ_λ A_c(λ) Σ_k K_{q,λ}(k)·F(s_k)·L(D(s_k), λ), s_k = q + (c_x − k_x, k_y − c_y)·p,\n * with K_{q,λ} the catalogue PSF resolved at the site's own field point (`resolveLensSampledPsfKernel`: the profile's 5 × 5 field\n * nodes × 5 wavelength nodes interpolated with centroid alignment; row index k_y increases with image +Y, `sensorPsfSourcePoint`),\n * F = T·A the field factor at the tap point (vignetting throughput × distortion area factor), D the scene ray (inverse radial\n * distortion, then the rectilinear or equisolid projection at the thin-lens image distance) and A_c(λ) the electrons per unit\n * spectral radiance on the axis (the tabulated path's channel response). Every tap of a site-centre query is a lattice point.\n *\n * The approximation (the only one). Resolving K_{q,λ} at every site and spectral node is what makes the exact method slow, so the\n * fast method resolves it exactly on a field grid and blends it bilinearly between the four grid points around each site:\n * K̃_{q,λ} = Σ_g b_g(q)·K_{g,λ}.\n * The grid subdivides each interval between the profile's field nodes into at least GRID_MINIMUM_SUBDIVISIONS cells, and into\n * more where the node kernels' intensity centroids move by more than GRID_CENTROID_STEP_SITES sites across the interval (lateral\n * colour moves the PSF across the frame; a blend of two shifted kernels is not the shifted kernel). Since the blend is linear,\n * the channel response folds into the grid kernels once per grid point and node, and each tap's signal is integrated from its\n * material's spectrum when the site is read (2.21.0; no material is folded into a kernel):\n * μ̃_c(q) = Σ_k F(s_k)·Σ_λ L_{m(s_k)}(λ)·Σ_g b_g(q)·C_{g,c}(k, λ), C_{g,c}(k, λ) = A_c(λ)·K_{g,λ}(k),\n * the blend taken along y once per grid column and native row, so a site costs (2R + 1)² taps of N nodes each instead of\n * (2R + 1)² scene queries per spectral node. Its error against the exact method is\n * bounded by ‖K̃ − K‖₁ times the brightest tap's signal; tests measure both (test/simulate-capture-lens-catalogue-fast.test.ts).\n *\n * The scene points. The mapping is the environment's (`undistortedImagePoint`, `lensProjectionDirectionValue`, the planar\n * provider's plane point), with the radial inverse solved by Newton's method instead of bisection: both converge to the same\n * root to rounding. Outside a circular fisheye's image circle (`outsideImageCircle: \"backward-ray\"`) and beyond the horizon the\n * scene radiance is zero, as in the capture.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { insideRadialImageCircle, lensProjectionDirectionValue } from \"../camera/lens-projection.js\";\nimport { resolveProjectionDistanceMm } from \"../motion/camera-rotation.js\";\nimport { prepareIlluminationVignettingThroughput, type IlluminationVignettingProfile } from \"../optics/illumination-vignetting.js\";\nimport { kernelCentroid, resolveLensSampledPsfKernel, type ResolveLensSampledPsfInput } from \"../optics/lens-psf-profile.js\";\nimport type { DisplayViewScene } from \"./expected-signal.js\";\n\n/** Fewest grid cells between neighboring profile field nodes (10 since #589: with 4, 0.4 % of quick frames failed the run-time check). */\nexport const CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS = 10;\n/**\n * #603 (2.22.0): the fewest cells on a fast request (on screen: 2.20.0's grid, its run-time fallbacks to the exact method included);\n * the full grid, {@link CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS}, on an exact one (the exports and the calculator).\n */\nexport const CATALOGUE_FAST_GRID_SPEED_SUBDIVISIONS = 4;\n/**\n * #603 (owner decision 2026-11-11): the lenses that keep the full grid on fast requests too, because the 4-cell grid's run-time\n * fallbacks to the exact method made their fast frames slower on average. Measured November 11, 2026 (arm64, Node.js 24; every\n * catalogue lens but the phone lenses, wide open and at max(f/8, widest), Siemens star and color patches, whole frames 192, 384 and\n * 768 pixels wide, two runs each; docs/LENS_CATALOGUE.md, \"Fast method\"): only this lens fell back, 4 of its 8 frames at 192 pixels\n * (f/2.8), 11.6 s each, against 0.17 s for the 10-cell grid.\n */\nexport const CATALOGUE_FAST_GRID_FULL_ON_SCREEN: readonly { lensId: string; fallbacksAtFourCells: { frames: number; fellBack: number; widthPixels: number } }[] =\n /* @__PURE__ */ Object.freeze([Object.freeze({ lensId: \"pv-15-2.8-fisheye-pro\", fallbacksAtFourCells: Object.freeze({ frames: 8, fellBack: 4, widthPixels: 192 }) })]);\n/** #603: the fewest grid cells for a lens on a fast or an exact request. */\nexport function catalogueFastGridSubdivisions(lensId: string, fast: boolean): number {\n return fast && !CATALOGUE_FAST_GRID_FULL_ON_SCREEN.some((entry) => entry.lensId === lensId) ? CATALOGUE_FAST_GRID_SPEED_SUBDIVISIONS : CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS;\n}\n/** Largest move of a node kernel's intensity centroid across one grid cell, in sites (sets finer grids where lateral color moves the PSF). */\nexport const CATALOGUE_FAST_GRID_CENTROID_STEP_SITES = 0.05;\n/**\n * Largest relative difference between the fast and the exact expected electrons that the run-time verification (one site per\n * CFA phase through the exact chain, `renderTabulatedNativeRaw`) accepts; above it the capture runs the exact method.\n */\nexport const CATALOGUE_FAST_VERIFICATION_TOLERANCE = 0.005;\n/** Largest cache window, in lattice points; a larger window is evaluated without caching. */\nconst WINDOW_LIMIT = 1 << 22;\nconst NEWTON_ITERATIONS = 60;\n\nexport interface CatalogueLensSignalInput {\n nativeWidth: number;\n nativeHeight: number;\n /** Site pitch, µm. */\n pitch: number;\n /** The catalogue PSF's optical state (profile, focal length, focus, f-number, defocus), as the site inputs' `psf.configuration.psf`. */\n psf: Omit<ResolveLensSampledPsfInput, \"fieldPointMm\" | \"wavelengthNm\">;\n /** Spectral nodes and, per CFA channel (red, green, blue), the expected electrons per unit spectral radiance at each node. */\n wavelengthsNm: readonly number[];\n electronsPerRadiance: readonly [Float64Array, Float64Array, Float64Array];\n /** The scene's chart materials (the tabulated path's material tables). */\n scene: Extract<DisplayViewScene, { kind: \"materials\" }>;\n /** CFA channel index (0 red, 1 green, 2 blue) of native site (x, y). */\n channelAt(x: number, y: number): number;\n /** The radial distortion profile (r_d = r·(1 + k1ρ² + k2ρ⁴ + k3ρ⁶), ρ = r / normalizationRadiusMm); absent without distortion. */\n distortion?: { normalizationRadiusMm: number; coefficients: { k1: number; k2: number; k3: number } };\n vignetting?: IlluminationVignettingProfile;\n projection: \"rectilinear\" | \"fisheye-equisolid-angle\";\n /** True for a catalogue fisheye: a sensor point outside the image circle looks straight back and sees no scene. */\n outsideImageCircleSeesNothing: boolean;\n focalLengthMm: number;\n focusDistanceM: number;\n /** The planar provider's plane distance and frame-unit scale. */\n distanceM: number;\n metresPerFrameUnit: number;\n /** #603: the fewest grid cells between neighbouring field nodes (default {@link CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS}). */\n gridSubdivisions?: number;\n /** Internal test hook: resolve every site's kernels exactly (the exact method's sum, slowly) instead of blending the grid. */\n exactKernels?: boolean;\n}\n\nexport interface CatalogueLensSignal {\n /** Starts a cache window of native sites [x0, x1) × [y0, y1) (see `DisplayViewExpectedSignal.window`). */\n window(x0: number, y0: number, x1: number, y1: number): void;\n /** Expected photo electrons of native site (x, y) for its own CFA channel. */\n site(x: number, y: number): number;\n /** Scene material lookups so far. */\n readonly lookups: number;\n /** Grid points per axis (columns, rows) and how many were resolved so far. */\n readonly grid: { columns: number; rows: number; resolved: number };\n}\n\n/**\n * The grid axes: each interval between neighboring profile field nodes split into max(GRID_MINIMUM_SUBDIVISIONS,\n * ⌈Δc / GRID_CENTROID_STEP_SITES⌉) equal cells, Δc the largest centroid move between the interval's two nodes over the other\n * axis's nodes and the wavelength nodes.\n */\nexport function catalogueFastGridAxes(psf: CatalogueLensSignalInput[\"psf\"], minimum = CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS): { x: number[]; y: number[] } {\n const profile = psf.profile, axes = profile.axes, fx = axes.fieldXmm, fy = axes.fieldYmm, wl = axes.wavelengthNm;\n const centroids = new Map<string, { x: number; y: number }>();\n for (const node of profile.nodes) {\n const c = node.coordinate;\n centroids.set(c.fieldXmm + \":\" + c.fieldYmm + \":\" + c.wavelengthNm, kernelCentroid(node.kernel));\n }\n const at = (x: number, y: number, nm: number): { x: number; y: number } => {\n const c = centroids.get(x + \":\" + y + \":\" + nm);\n if (!c) throw new InvalidConfigurationError(\"lens.catalogue fast: the PSF profile lacks a field node.\");\n return c;\n };\n const axis = (own: readonly number[], other: readonly number[], along: boolean): number[] => {\n const out: number[] = [];\n for (let i = 0; i + 1 < own.length; i++) {\n let move = 0;\n for (const o of other) for (const nm of wl) {\n const a = along ? at(own[i]!, o, nm) : at(o, own[i]!, nm), b = along ? at(own[i + 1]!, o, nm) : at(o, own[i + 1]!, nm);\n move = Math.max(move, Math.hypot(a.x - b.x, a.y - b.y));\n }\n const cells = Math.max(minimum, Math.ceil(move / CATALOGUE_FAST_GRID_CENTROID_STEP_SITES - 1e-9));\n for (let k = 0; k < cells; k++) out.push(own[i]! + (own[i + 1]! - own[i]!) * k / cells);\n }\n out.push(own[own.length - 1]!);\n return out;\n };\n return { x: axis(fx, fy, true), y: axis(fy, fx, false) };\n}\n\n/** The cell [i, i + 1] of an ascending axis holding v (clamped to the ends) and v's weight toward i + 1. */\nfunction cellOf(axis: readonly number[], v: number): { i: number; f: number } {\n let lo = 0, hi = axis.length - 2;\n while (lo < hi) { const mid = (lo + hi + 1) >> 1; if (axis[mid]! <= v) lo = mid; else hi = mid - 1; }\n const f = (v - axis[lo]!) / (axis[lo + 1]! - axis[lo]!);\n return { i: lo, f: Math.min(1, Math.max(0, f)) };\n}\n\n/**\n * Internal test hook (never set by the engine): `exactKernels` makes the facade's signals resolve every site's kernels exactly;\n * `onInput` receives each input the facade builds, so a test can compare the grid blend with the exact sum site by site.\n */\nexport interface CatalogueLensSignalTestHook { exactKernels?: boolean; onInput?(input: CatalogueLensSignalInput): void }\nlet testHook: CatalogueLensSignalTestHook | undefined;\nexport function setCatalogueLensSignalTestHook(hook: CatalogueLensSignalTestHook | undefined): void { testHook = hook; }\n\n/** The fast method's expected signal (see the module comment). */\nexport function createCatalogueLensSignal(given: CatalogueLensSignalInput): CatalogueLensSignal {\n testHook?.onInput?.(given);\n const input = testHook?.exactKernels ? { ...given, exactKernels: true } : given;\n const { nativeWidth: W, nativeHeight: H, psf, wavelengthsNm, electronsPerRadiance: A, scene, channelAt } = input;\n const mmPerSite = input.pitch / 1000, nodes = wavelengthsNm.length;\n const first = psf.profile.nodes[0];\n if (!first) throw new InvalidConfigurationError(\"lens.catalogue fast: the PSF profile has no nodes.\");\n const kw = first.kernel.widthSamples, kh = first.kernel.heightSamples, cx = first.kernel.centerSampleX, cy = first.kernel.centerSampleY, taps = kw * kh;\n for (const node of psf.profile.nodes) if (node.kernel.widthSamples !== kw || node.kernel.heightSamples !== kh || node.kernel.centerSampleX !== cx || node.kernel.centerSampleY !== cy)\n throw new InvalidConfigurationError(\"lens.catalogue fast: the PSF profile's kernels differ in size.\");\n // Lattice reach of the taps around a site: x from −cx … kw − 1 − cx (as c_x − k_x), y from −cy … kh − 1 − cy.\n const reachLeft = kw - 1 - cx, reachRight = cx, reachUp = cy, reachDown = kh - 1 - cy;\n // Each material's spectral radiance at the nodes (a neutral one: its reflectance times the white radiance). Only the spectra are\n // kept: a site's signal is integrated from its taps' material spectra when it is read, so no material is folded into a kernel.\n const M = scene.materials.length;\n const spectra = scene.materials.map((m) => (\"neutral\" in m ? Float64Array.from(scene.whiteRadiance, (w) => m.neutral * w) : Float64Array.from(m.radiance)));\n const tableSize = 3 * taps * nodes;\n // A_c(λ_n)·K_n(k) for the kernels of one field point, at ((c·taps + k)·nodes + n): the channel response per node, no material.\n const foldKernels = (fieldXmm: number, fieldYmm: number): Float64Array => {\n const table = new Float64Array(tableSize);\n for (let n = 0; n < nodes; n++) {\n const kernel = resolveLensSampledPsfKernel({ ...psf, wavelengthNm: wavelengthsNm[n]!, fieldPointMm: { x: fieldXmm, y: fieldYmm } }).normalizedIntensity;\n if (kernel.length !== taps) throw new InvalidConfigurationError(\"lens.catalogue fast: a resolved kernel differs in size.\");\n for (let c = 0; c < 3; c++) {\n const a = A[c]![n]!;\n for (let k = 0; k < taps; k++) table[(c * taps + k) * nodes + n] = a * kernel[k]!;\n }\n }\n return table;\n };\n // The field grid, resolved lazily (a region render resolves only the grid points around it).\n const axes = catalogueFastGridAxes(psf, input.gridSubdivisions), gx = axes.x, gy = axes.y, GX = gx.length;\n const tables: (Float64Array | undefined)[] = new Array(GX * gy.length);\n let resolved = 0;\n const tableAt = (i: number, j: number): Float64Array => {\n const k = j * GX + i;\n let t = tables[k];\n if (!t) { t = foldKernels(gx[i]!, gy[j]!); tables[k] = t; resolved++; }\n return t;\n };\n // Each native column's and row's grid cell and blend weight (field +Y up: row y sits at −(y + ½ − H/2)·p).\n const cellX = new Int32Array(W), weightX = new Float64Array(W), cellY = new Int32Array(H), weightY = new Float64Array(H);\n for (let x = 0; x < W; x++) { const c = cellOf(gx, (x + 0.5 - W / 2) * mmPerSite); cellX[x] = c.i; weightX[x] = c.f; }\n for (let y = 0; y < H; y++) { const c = cellOf(gy, -(y + 0.5 - H / 2) * mmPerSite); cellY[y] = c.i; weightY[y] = c.f; }\n\n // The scene point and field factor of a native sensor point (mm, +Y down); factor 0 where the scene radiance is zero.\n const pd = resolveProjectionDistanceMm(input.focalLengthMm, input.focusDistanceM).projectionDistanceMm;\n const planeScale = input.distanceM / input.metresPerFrameUnit;\n const throughputAt = input.vignetting ? prepareIlluminationVignettingThroughput(input.vignetting) : undefined;\n const distortion = input.distortion, rectilinear = input.projection === \"rectilinear\";\n let mu = 0, mv = 0, mf = 0;\n const map = (xMm: number, yMm: number): void => {\n const imageX = xMm, imageY = -yMm;\n let idealX = imageX, idealY = imageY, area = 1;\n if (distortion) {\n const { k1, k2, k3 } = distortion.coefficients, norm = distortion.normalizationRadiusMm, rd = Math.hypot(imageX, imageY) / norm;\n let rho = rd;\n if (rd > 0) {\n // Newton's method on ρ·s(ρ) = ρ_d (monotonic over the profile's validated range), from ρ = ρ_d.\n let converged = false;\n for (let it = 0; it < NEWTON_ITERATIONS; it++) {\n const r2 = rho * rho, value = rho * (1 + k1 * r2 + k2 * r2 * r2 + k3 * r2 * r2 * r2) - rd, slope = 1 + 3 * k1 * r2 + 5 * k2 * r2 * r2 + 7 * k3 * r2 * r2 * r2;\n if (!(slope > 0)) break;\n const step = value / slope;\n rho -= step;\n if (Math.abs(step) <= 4 * Number.EPSILON * rho) { converged = true; break; }\n }\n if (!converged || !(rho > 0)) throw new InvalidConfigurationError(\"lens.catalogue fast: the inverse distortion did not converge.\");\n }\n const r2 = rho * rho, s = 1 + k1 * r2 + k2 * r2 * r2 + k3 * r2 * r2 * r2, derivative = 1 + 3 * k1 * r2 + 5 * k2 * r2 * r2 + 7 * k3 * r2 * r2 * r2;\n if (rd > 0) { idealX = imageX / s; idealY = imageY / s; }\n area = 1 / (s * derivative);\n if (!(area > 0) || !Number.isFinite(area)) throw new InvalidConfigurationError(\"lens.catalogue fast: the distortion area factor must stay finite and positive.\");\n }\n const factor = (throughputAt ? throughputAt({ x: imageX, y: imageY }) : 1) * area;\n if (rectilinear) { mu = idealX / pd * planeScale; mv = idealY / pd * planeScale; mf = factor; return; }\n if (input.outsideImageCircleSeesNothing && !insideRadialImageCircle(input.projection, pd, Math.hypot(idealX, idealY))) { mf = 0; return; }\n const d = lensProjectionDirectionValue(input.projection, pd, idealX, idealY);\n if (!(d.z > 0)) { mf = 0; return; }\n mu = d.x * (input.distanceM / d.z) / input.metresPerFrameUnit; mv = d.y * (input.distanceM / d.z) / input.metresPerFrameUnit; mf = factor;\n };\n let lookups = 0;\n let lm = 0, lf = 0;\n /** The material and field factor of lattice point (p, q) (sites from the top-left site, the lattice formula). */\n const lattice = (p: number, q: number): void => {\n map((p + 0.5 - W / 2) * mmPerSite, (q + 0.5 - H / 2) * mmPerSite);\n lf = mf;\n if (mf === 0) { lm = 0; return; }\n const m = scene.materialAt(mu, mv);\n if (!(m >= 0 && m < M) || !Number.isInteger(m)) throw new InvalidConfigurationError(\"Unknown chart material.\");\n lm = m; lookups++;\n };\n // The window's lattice: points [wx0, wx0 + ww) × [wy0, wy0 + wh).\n let wx0 = 0, wy0 = 0, ww = 0, wh = 0, winMaterial = new Int32Array(0), winFactor = new Float64Array(0);\n const window = (x0: number, y0: number, x1: number, y1: number): void => {\n const w = x1 - x0 + reachLeft + reachRight, h = y1 - y0 + reachUp + reachDown;\n if (!(w > 0 && h > 0) || w * h > WINDOW_LIMIT) { ww = 0; wh = 0; return; }\n wx0 = x0 - reachLeft; wy0 = y0 - reachUp; ww = w; wh = h;\n if (winMaterial.length < w * h) { winMaterial = new Int32Array(w * h); winFactor = new Float64Array(w * h); }\n for (let q = 0; q < h; q++) for (let p = 0; p < w; p++) { lattice(wx0 + p, wy0 + q); winMaterial[q * w + p] = lm; winFactor[q * w + p] = lf; }\n };\n // A site's kernel is the bilinear blend of its cell's four grid kernels. Blended along y first, once per grid column and native\n // row (every site of a row has the same fy): R_i(y) = (1 − fy)·T(i, j) + fy·T(i, j + 1), kept for the row the sites are on.\n const rowTables: Float64Array[] = [], rowOf = new Int32Array(GX).fill(-1);\n const rowTable = (i: number, y: number): Float64Array => {\n let table = rowTables[i];\n if (!table) table = rowTables[i] = new Float64Array(tableSize);\n if (rowOf[i] !== y) {\n const j = cellY[y]!, fy = weightY[y]!, a = tableAt(i, j), b = tableAt(i, j + 1);\n for (let e = 0; e < tableSize; e++) table[e] = (1 - fy) * a[e]! + fy * b[e]!;\n rowOf[i] = y;\n }\n return table;\n };\n const site = (x: number, y: number): number => {\n const c = channelAt(x, y);\n let r0: Float64Array, r1: Float64Array, fx: number;\n if (input.exactKernels) { r0 = r1 = foldKernels((x + 0.5 - W / 2) * mmPerSite, -(y + 0.5 - H / 2) * mmPerSite); fx = 0; }\n else { const i = cellX[x]!; r0 = rowTable(i, y); r1 = rowTable(i + 1, y); fx = weightX[x]!; }\n const inside = ww > 0 && x - reachLeft >= wx0 && y - reachUp >= wy0 && x + reachRight < wx0 + ww && y + reachDown < wy0 + wh;\n const channelBase = c * taps * nodes;\n // Each tap's signal is integrated from its material's spectrum against the two row-blended kernels per node; the blend along x\n // is linear, so it is applied to the two sums.\n let s0 = 0, s1 = 0;\n for (let ky = 0, k = 0; ky < kh; ky++) {\n const q = y + ky - cy;\n for (let kx = 0; kx < kw; kx++, k++) {\n const p = x + cx - kx;\n let m: number, f: number;\n if (inside) { const at = (q - wy0) * ww + p - wx0; m = winMaterial[at]!; f = winFactor[at]!; } else { lattice(p, q); m = lm; f = lf; }\n if (f === 0) continue;\n const L = spectra[m]!, at = channelBase + k * nodes;\n let w0 = 0, w1 = 0;\n if (fx === 0) for (let n = 0; n < nodes; n++) w0 += r0[at + n]! * L[n]!;\n else for (let n = 0; n < nodes; n++) { const l = L[n]!; w0 += r0[at + n]! * l; w1 += r1[at + n]! * l; }\n s0 += f * w0; s1 += f * w1;\n }\n }\n return fx === 0 ? s0 : (1 - fx) * s0 + fx * s1;\n };\n return {\n window, site,\n get lookups(): number { return lookups; },\n get grid(): { columns: number; rows: number; resolved: number } { return { columns: GX, rows: gy.length, resolved }; }\n };\n}\n\n/** The `raw.expectedSignal` and `fast.lens.catalogue` assumptions of a capture the fast method rendered (kept here, out of the capture bundle's entry). */\nexport function catalogueFastAssumptions(run: { columns: number; rows: number; resolved: number; verificationRelativeDifference: number; subdivisions: number }):\n { id: string; value: Record<string, unknown>; explanation: string }[] {\n const tolerance = CATALOGUE_FAST_VERIFICATION_TOLERANCE, cells = run.subdivisions, step = CATALOGUE_FAST_GRID_CENTROID_STEP_SITES;\n return [{ id: \"raw.expectedSignal\", value: { method: \"per-site-integrated-electrons-catalogue-psf-field-grid\", verificationSites: 4, tolerance,\n verificationRelativeDifference: run.verificationRelativeDifference },\n explanation: \"Each native site's expected photo electrons are integrated per site when the site is read: the sum over the PSF taps of the field factor (vignetting × distortion area factor) times the \" +\n \"grid-blended kernel per spectral node times the channel response, integrated with each tap's material spectrum (see fast.lens.catalogue). The sensor stage (dark charge, Poisson draws, read noise, ADC) \" +\n \"is the native one with each site's own seeds. One site of each CFA phase ran the exact chain (the environment PSF quadrature): its readout was reproduced bit for bit and \" +\n \"its electrons agreed with the fast ones within the tolerance (verificationRelativeDifference: the largest difference there).\" },\n { id: \"fast.lens.catalogue\", value: { method: \"field-grid-bilinear-psf\", gridColumns: run.columns, gridRows: run.rows, gridPointsResolved: run.resolved,\n minimumSubdivisions: cells, centroidStepSites: step, verificationTolerance: tolerance },\n explanation: \"Fast method (#568), an approximation of the exact one: the catalogue PSF is resolved exactly on a field grid (each interval between the profile's field nodes \" +\n \"split into at least \" + cells + \" cells (#603: \" + CATALOGUE_FAST_GRID_SPEED_SUBDIVISIONS + \" on a fast request, \" + CATALOGUE_FAST_GRID_MINIMUM_SUBDIVISIONS + \" on an exact one and for the lenses of CATALOGUE_FAST_GRID_FULL_ON_SCREEN), more where the node kernels' centroids move by over \" + step + \" site per cell), and each site takes the bilinear blend of its \" +\n \"four grid points' kernels instead of its own. Its error is at most the kernels' L1 difference times the brightest tap's signal; docs/LENS_CATALOGUE.md (\\\"Fast method\\\") \" +\n \"records it measured against the exact method. Distortion, vignetting and projection are the exact method's (the radial inverse by Newton's method, equal to rounding).\" }];\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import type { ResolveLensSampledPsfInput } from "../optics/lens-psf-profile.js";
2
2
  import type { PlanarSceneRadianceProvider } from "./scene-radiance.js";
3
- import { type LargeDefocusKernel } from "./large-defocus-lattice.js";
3
+ import type { LargeDefocusKernel } from "./large-defocus-lattice.js";
4
4
  export interface DiffractedPlanarProviderInput {
5
5
  base: PlanarSceneRadianceProvider;
6
6
  /** The optical state of the sampled PSF, as for `resolveLensSampledPsf`, without field point and wavelength. Unused with `siteKernels`. */
@@ -55,8 +55,7 @@
55
55
  import { InvalidConfigurationError } from "../core/configuration-error.js";
56
56
  import { isInternalSceneRadianceEvaluator, markInternalSceneRadianceEvaluator, registerInternalRadianceAccess } from "../core/internal-radiance-evaluator.js";
57
57
  import { createIrradianceConvolutionInteriorRunner } from "../optics/irradiance-convolution.js";
58
- import { siteDiffractionKernel } from "../optics/site-diffraction-kernel.js";
59
- import { LARGE_DEFOCUS_CACHE_BYTES, createLargeDefocusNodeLattice } from "./large-defocus-lattice.js";
58
+ import { loadedKit, qualityKit } from "./on-demand-kits.js";
60
59
  /** Rows of native sites per convolution band, and the bands kept. Banding changes memory only, never values. */
61
60
  const BAND_ROWS = 32;
62
61
  const CACHED_BANDS = 4;
@@ -90,7 +89,7 @@ export function createDiffractedPlanarProvider(input) {
90
89
  if (!siteKernels && !input.psf && !large)
91
90
  throw new InvalidConfigurationError("The object-space convolution needs a PSF or site kernels.");
92
91
  const kernels = large ? [] : wavelengthsNm.map((wavelengthNm) => siteKernels ? checkedSiteKernel(siteKernels(wavelengthNm), R) :
93
- siteDiffractionKernel(input.psf, wavelengthNm, pitch, R, "Diffraction kernels must sample the site pitch exactly."));
92
+ loadedKit(qualityKit).siteDiffractionKernel(input.psf, wavelengthNm, pitch, R, "Diffraction kernels must sample the site pitch exactly."));
94
93
  // #492: each site kernel's non-zero taps as grid offsets, in the gather's order.
95
94
  const taps = siteKernels && !large ? kernels.map((kernel) => kernelTaps(kernel, R, NW + 2 * R)) : [];
96
95
  const gridWidth = NW + 2 * R;
@@ -171,7 +170,8 @@ export function createDiffractedPlanarProvider(input) {
171
170
  const shift = shifts[s];
172
171
  const vOf = (lj) => shift.y === 0 ? -(lj - M + 0.5 - H / 2) * g : -(lj - M + 0.5 + shift.y - H / 2) * g;
173
172
  const uOf = (li) => shift.x === 0 ? (li - M + 0.5 - W / 2) * g : (li - M + 0.5 + shift.x - W / 2) * g;
174
- lattice = largeLattices[s] = createLargeDefocusNodeLattice({ kernel: large, wavelengthsNm, capacityBytes: LARGE_DEFOCUS_CACHE_BYTES / shifts.length, ...(input.onConvolution ? { onTile: input.onConvolution } : {}),
173
+ const kit = loadedKit(qualityKit);
174
+ lattice = largeLattices[s] = kit.createLargeDefocusNodeLattice({ kernel: large, wavelengthsNm, capacityBytes: kit.LARGE_DEFOCUS_CACHE_BYTES / shifts.length, ...(input.onConvolution ? { onTile: input.onConvolution } : {}),
175
175
  source: (x0, y0, width, height) => {
176
176
  const size = width * height;
177
177
  let materialOf;
@@ -1 +1 @@
1
- {"version":3,"file":"diffraction-provider.js","sourceRoot":"","sources":["../../src/facade/diffraction-provider.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Fast execution of `simulateCapture`'s `lens.diffraction` (2.1): an object-space convolution in the scene\n * provider, instead of one scene query per PSF tap in the environment PSF quadrature.\n *\n * The environment quadrature computes, at each site centre q and spectral node λ,\n * E(q, λ) = Σ_k K_λ(k)·T·L(s_k(q), λ),\n * where s_k(q) is the tap's source point (`sensorPsfSourcePoint`), L the scene radiance at the plane point\n * that source point sees, and T the radiance-to-irradiance factor. For the facade's planar scene seen\n * through the ideal rectilinear projection with a still camera and no lens field mapping, field throughput or\n * pupil rays:\n * - T is the same at every sensor point (paraxial π/(4·N_w²), no cos⁴ term), and\n * - with the kernel sampled on the site pitch, every source point is the centre of another site, so the plane\n * points form one regular lattice: u = (i + ½ − W/2)·2/w, v = −(j + ½ − H/2)·2/w (frame units, native\n * site (i, j), W×H native sites, w output width).\n * So E(q, λ) = T·B(q, λ) with B = K_λ ⊛ L sampled on that lattice: the same sum, in a different floating-point\n * order. B is computed once per spectral node with the engine's isoplanatic convolution\n * (`calculateIrradianceConvolution`, kernels from `resolveLensPsfConvolutionKernels`, exact site sampling) over a\n * grid that holds every source (the native raster plus the kernel radius on each side), in row bands; each band gathers only\n * its own values, the grid's interior (#419, `createIrradianceConvolutionInteriorRunner`: each value bit-identical to\n * `calculateIrradianceConvolution`'s there, without the 2R rows and columns of the band's grid that no query reads). The\n * provider then answers each site-centre query with B instead of L, and the environment request declares no\n * PSF. Incoherent imaging is a linear superposition of intensity PSFs, so convolving radiance on the object\n * plane and convolving irradiance on the image plane agree for a planar object and a space-invariant PSF\n * (MIT OpenCourseWare 2.71, lecture 22, free; also see: Goodman, Introduction to Fourier Optics, 4th ed., §7.1).\n *\n * With an anti-aliasing point-splitting filter (2.1, `sensor.antiAliasing`) the environment queries the PSF taps\n * around each pre-filter source point q − a (a = a split offset) instead of around q. Those taps lie on the site\n * lattice shifted by a, so the same argument holds on each shifted lattice: B is computed once per distinct\n * fractional shift (offsets that differ by whole sites share one lattice; the centred four-spot filter with a\n * one-site separation needs a single half-site-shifted lattice) over the native raster widened by the largest\n * offset, and the environment's spatial quadrature still forms the weighted split sum.\n *\n * Region renders (2.6, `window`): only the lattice rows and columns that the region's sites can query (the window\n * plus the largest offset on each side) are convolved, over a grid that adds the kernel radius on each side. Every\n * output value is the same gather as in the whole render: the grid always holds every tap of every value it keeps\n * (real scene radiance out to the kernel radius, never a truncated edge), the single kernel patch does not depend on\n * the grid's origin, and the gather (`convolveIrradianceRows`, and its interior form) sums each value in a fixed tap order (v outer, u inner). Narrowing\n * the grid therefore removes only values that no query reads, and the kept values are bit-identical.\n *\n * A query that does not land on one of the lattices (within 1e-6 site) is refused rather than approximated: the\n * facade uses this path only when the lattice argument above holds. A query outside the window is refused too.\n *\n * Defocus (#492, `lens.defocus`): the same argument holds for any space-invariant kernel on the site lattice, so the facade\n * passes `siteKernels` instead (the geometric defocus disc, or each node's diffraction kernel convolved with it). Their radius\n * may exceed the public 32-site convolution limit, so this path does not call `calculateIrradianceConvolution`: it checks the\n * samples and the kernel sums as that function does and gathers only the band's own values (`gatherInterior`), each summed\n * over the taps in the same fixed order (v outer, u inner, ascending; zero taps skipped, which adds exact zeros only). Like\n * the diffraction path (#419), it does not compute the 2R grid rows and columns around a band.\n *\n * Large defocus kernels (#564, `largeKernel`): above 64 sites the disc is convolved by runs in fixed tiles instead of bands\n * (`large-defocus-lattice.ts`, `site-kernel-runs.ts`), each node's diffraction kernel after it; the plane points and the\n * material lookup are the bands' own, and values stay independent of the window.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { isInternalSceneRadianceEvaluator, markInternalSceneRadianceEvaluator, registerInternalRadianceAccess } from \"../core/internal-radiance-evaluator.js\";\nimport type { SceneRadianceEvaluationRequest, SceneRadianceEvaluationResult } from \"../schema/scene-radiance.js\";\nimport { createIrradianceConvolutionInteriorRunner } from \"../optics/irradiance-convolution.js\";\nimport { siteDiffractionKernel } from \"../optics/site-diffraction-kernel.js\";\nimport type { ResolveLensSampledPsfInput } from \"../optics/lens-psf-profile.js\";\nimport type { PlanarSceneRadianceProvider } from \"./scene-radiance.js\";\nimport { LARGE_DEFOCUS_CACHE_BYTES, createLargeDefocusNodeLattice, type LargeDefocusKernel, type LargeDefocusNodeLattice } from \"./large-defocus-lattice.js\";\n\n/** Rows of native sites per convolution band, and the bands kept. Banding changes memory only, never values. */\nconst BAND_ROWS = 32;\nconst CACHED_BANDS = 4;\nconst LATTICE_TOLERANCE_SITES = 1e-6;\n\nexport interface DiffractedPlanarProviderInput {\n base: PlanarSceneRadianceProvider;\n /** The optical state of the sampled PSF, as for `resolveLensSampledPsf`, without field point and wavelength. Unused with `siteKernels`. */\n psf?: Omit<ResolveLensSampledPsfInput, \"fieldPointMm\" | \"wavelengthNm\">;\n /**\n * #492: the kernel of each spectral node on the site lattice, (2·kernelRadius + 1)² taps in row-major order, applied\n * instead of the diffraction kernels of `psf` (the defocus disc, or each node's diffraction kernel convolved with it).\n * Any radius; each kernel's sum may not exceed 1 + 2^-20.\n */\n siteKernels?: (wavelengthNm: number) => Float64Array;\n /** Spectral nodes the environment queries (the profile's wavelength nodes). */\n wavelengthsNm: readonly number[];\n kernelRadius: number;\n nativeWidth: number;\n nativeHeight: number;\n /** Output (active) width in sites: frame units are 2/outputWidth per site. */\n outputWidth: number;\n sitePitchMicrometers: number;\n /** Planar geometry of the base provider, to map query directions to plane points exactly as it does. */\n distanceM: number;\n metresPerFrameUnit: number;\n /**\n * Offsets of the query points from the site centres, in sites (+x right, +y down): the anti-aliasing split\n * offsets with their sign reversed (the environment queries q − a). Default: one zero offset.\n */\n queryOffsetsSites?: readonly { x: number; y: number }[];\n /**\n * Region renders (2.6): the native sites that will be queried (x, y, width, height in the native raster). Only the\n * lattice they can reach is convolved; values are bit-identical to the whole render's. Default: the whole raster.\n */\n window?: { x: number; y: number; width: number; height: number };\n /** Called with the duration in ms of each band convolution (diagnostics only; never changes values). */\n onConvolution?: (milliseconds: number) => void;\n /**\n * #564: a defocus kernel above the direct radius, convolved by runs in fixed tiles (`large-defocus-lattice.ts`), with each\n * node's diffraction kernel after it; used instead of `siteKernels` and `psf` (`kernelRadius` is then unused).\n */\n largeKernel?: LargeDefocusKernel;\n /** #553: a field-varying kernel by zones (the cat's eye), used instead of `siteKernels` in the gather; needs `siteKernels`. */\n fieldZones?: SiteKernelFieldZones;\n}\n\n/** Internal (not exported from the package): the base provider with diffraction applied as an object-space convolution. */\nexport function createDiffractedPlanarProvider(input: DiffractedPlanarProviderInput): PlanarSceneRadianceProvider {\n const { base, wavelengthsNm, nativeWidth: W, nativeHeight: H, kernelRadius: R } = input;\n const g = 2 / input.outputWidth, pitch = input.sitePitchMicrometers;\n const index = new Map(wavelengthsNm.map((nm, i) => [nm, i]));\n // One lattice per distinct fractional query offset; M extra sites per side hold the offset queries.\n const offsets = input.queryOffsetsSites ?? [{ x: 0, y: 0 }];\n const fraction = (value: number): number => { const f = value - Math.floor(value); return f > 1 - LATTICE_TOLERANCE_SITES ? 0 : f < LATTICE_TOLERANCE_SITES ? 0 : f; };\n const shifts: { x: number; y: number }[] = [];\n for (const o of offsets) {\n const f = { x: fraction(o.x), y: fraction(o.y) };\n if (!shifts.some((s) => Math.abs(s.x - f.x) <= LATTICE_TOLERANCE_SITES && Math.abs(s.y - f.y) <= LATTICE_TOLERANCE_SITES)) shifts.push(f);\n }\n const M = Math.max(0, ...offsets.map((o) => Math.ceil(Math.max(Math.abs(o.x), Math.abs(o.y)) - LATTICE_TOLERANCE_SITES)));\n const LW = W + 2 * M, LH = H + 2 * M;\n // Lattice window (indices i + M, j + M): the sites the region queries plus the largest offset on each side, clipped\n // to the lattice. A site i queries i + floor(offset), and floor(offset) lies in [-M, M].\n const win = input.window ?? { x: 0, y: 0, width: W, height: H };\n const lx0 = Math.max(0, win.x), lx1 = Math.min(LW, win.x + win.width + 2 * M);\n const ly0 = Math.max(0, win.y), ly1 = Math.min(LH, win.y + win.height + 2 * M);\n if (!(lx0 < lx1 && ly0 < ly1)) throw new InvalidConfigurationError(\"Diffraction window must overlap the native raster.\");\n const NW = lx1 - lx0;\n // One kernel per wavelength, on the site grid, from the engine's own tap-to-site mapping (field point 0, 0); kept across calls.\n const siteKernels = input.siteKernels, large = input.largeKernel;\n if (!siteKernels && !input.psf && !large) throw new InvalidConfigurationError(\"The object-space convolution needs a PSF or site kernels.\");\n const kernels = large ? [] : wavelengthsNm.map((wavelengthNm) => siteKernels ? checkedSiteKernel(siteKernels(wavelengthNm), R) :\n siteDiffractionKernel(input.psf!, wavelengthNm, pitch, R, \"Diffraction kernels must sample the site pitch exactly.\"));\n // #492: each site kernel's non-zero taps as grid offsets, in the gather's order.\n const taps = siteKernels && !large ? kernels.map((kernel) => kernelTaps(kernel, R, NW + 2 * R)) : [];\n const gridWidth = NW + 2 * R;\n const zonedGather = input.fieldZones && siteKernels ? createZonedGather(input.fieldZones, R, gridWidth, W, H, M) : undefined;\n const now = (): number => globalThis.performance?.now() ?? Date.now();\n const bands = new Map<number, Float64Array[][]>();\n const materialAt = base.chartMaterialAt?.bind(base), materialRadiance = base.materialRadiance?.bind(base);\n function band(b: number): Float64Array[][] {\n const cached = bands.get(b);\n if (cached) { bands.delete(b); bands.set(b, cached); return cached; }\n const started = input.onConvolution ? now() : 0;\n const y0 = ly0 + b * BAND_ROWS, rows = Math.min(BAND_ROWS, ly1 - y0), gridHeight = rows + 2 * R, size = gridWidth * gridHeight;\n // #453: the band's shifts × spectral nodes convolutions share one geometry, validated once (the first with every check of\n // calculateIrradianceConvolution; every later one still checks its samples and kernel). #419: only the band's own rows × NW\n // values are gathered (the grid's interior), each bit-identical to calculateIrradianceConvolution's value there.\n const convolve = siteKernels ? undefined : createIrradianceConvolutionInteriorRunner({ schemaVersion: \"0.1.0\", width: gridWidth, height: gridHeight, kernelRadius: R,\n patchWidth: gridWidth, patchHeight: gridHeight, boundary: \"zero-outside-grid\" });\n const values = shifts.map((shift) => {\n // The plane point of lattice grid sample (gx, gy) of this shift, the same expressions for both fills below.\n const vOf = (gy: number): number => shift.y === 0 ? -(y0 + gy - R - M + 0.5 - H / 2) * g : -(y0 + gy - R - M + 0.5 + shift.y - H / 2) * g;\n const uOf = (x: number): number => shift.x === 0 ? (x - R - M + 0.5 - W / 2) * g : (x - R - M + 0.5 + shift.x - W / 2) * g;\n // #453, material scenes (chart presets and caller material scenes): radianceAt(u, v, nm) is materialRadiance(chartMaterialAt(u, v), nm)\n // (scene-radiance.ts), so the material is looked up once per lattice point and each node's samples come from one\n // materialRadiance per material present, the same numbers as one radianceAt per point and node.\n let materialOf: Int32Array | undefined;\n if (materialAt && materialRadiance) {\n materialOf = new Int32Array(size);\n for (let gy = 0; gy < gridHeight; gy++) {\n const v = vOf(gy);\n for (let gx = 0, x = lx0; gx < gridWidth; gx++, x++) materialOf[gy * gridWidth + gx] = materialAt(uOf(x), v);\n }\n }\n return wavelengthsNm.map((nm, w) => {\n const samples = new Float64Array(size);\n if (materialOf) {\n const radiance = new Map<number, number>();\n for (let i = 0; i < size; i++) {\n const m = materialOf[i]!;\n let value = radiance.get(m);\n if (value === undefined) { value = materialRadiance!(m, nm); radiance.set(m, value); }\n samples[i] = value;\n }\n } else {\n for (let gy = 0; gy < gridHeight; gy++) {\n const v = vOf(gy);\n for (let gx = 0, x = lx0; gx < gridWidth; gx++, x++) samples[gy * gridWidth + gx] = base.radianceAt(uOf(x), v, nm);\n }\n }\n if (zonedGather) return zonedGather(samples, lx0, y0, NW, rows);\n if (!convolve) return gatherInterior(samples, taps[w]!, gridWidth, NW, rows, R);\n return convolve(samples, kernels[w]!);\n });\n });\n bands.set(b, values);\n if (bands.size > CACHED_BANDS) bands.delete(bands.keys().next().value!);\n if (input.onConvolution) input.onConvolution(now() - started);\n return values;\n }\n // #564: one run lattice per shift (lattice points li, lj), its samples the base radiance at the same plane points as the bands'.\n const largeLattices: (LargeDefocusNodeLattice | undefined)[] = [];\n function largeLattice(s: number): LargeDefocusNodeLattice {\n let lattice = largeLattices[s];\n if (!lattice) {\n const shift = shifts[s]!;\n const vOf = (lj: number): number => shift.y === 0 ? -(lj - M + 0.5 - H / 2) * g : -(lj - M + 0.5 + shift.y - H / 2) * g;\n const uOf = (li: number): number => shift.x === 0 ? (li - M + 0.5 - W / 2) * g : (li - M + 0.5 + shift.x - W / 2) * g;\n lattice = largeLattices[s] = createLargeDefocusNodeLattice({ kernel: large!, wavelengthsNm, capacityBytes: LARGE_DEFOCUS_CACHE_BYTES / shifts.length, ...(input.onConvolution ? { onTile: input.onConvolution } : {}),\n source: (x0, y0, width, height) => {\n const size = width * height;\n let materialOf: Int32Array | undefined;\n if (materialAt && materialRadiance) {\n materialOf = new Int32Array(size);\n for (let y = 0; y < height; y++) { const v = vOf(y0 + y); for (let x = 0; x < width; x++) materialOf[y * width + x] = materialAt(uOf(x0 + x), v); }\n }\n return (node: number): Float64Array => {\n const nm = wavelengthsNm[node]!, samples = new Float64Array(size);\n if (materialOf) {\n const radiance = new Map<number, number>();\n for (let k = 0; k < size; k++) {\n const m = materialOf[k]!;\n let value = radiance.get(m);\n if (value === undefined) { value = materialRadiance!(m, nm); radiance.set(m, value); }\n samples[k] = value;\n }\n } else for (let y = 0; y < height; y++) { const v = vOf(y0 + y); for (let x = 0; x < width; x++) samples[y * width + x] = base.radianceAt(uOf(x0 + x), v, nm); }\n return samples;\n };\n } });\n }\n return lattice;\n }\n /** The convolved value of shift s, node index w, at lattice point (li, lj) inside the window. */\n function valueAt(s: number, w: number, li: number, lj: number): number {\n return large ? largeLattice(s).valueAt(w, li, lj) : band(Math.floor((lj - ly0) / BAND_ROWS))[s]![w]![((lj - ly0) % BAND_ROWS) * NW + li - lx0]!;\n }\n function blurredAt(u: number, v: number, nm: number): number {\n const w = index.get(nm), fi = u / g - 0.5 + W / 2, fj = -v / g - 0.5 + H / 2;\n if (w !== undefined) for (let s = 0; s < shifts.length; s++) {\n const shift = shifts[s]!, i = Math.round(fi - shift.x), j = Math.round(fj - shift.y);\n if (Math.abs(fi - shift.x - i) > LATTICE_TOLERANCE_SITES || Math.abs(fj - shift.y - j) > LATTICE_TOLERANCE_SITES) continue;\n const li = i + M, lj = j + M;\n if (li < lx0 || lj < ly0 || li >= lx1 || lj >= ly1) break;\n return valueAt(s, w, li, lj);\n }\n throw new InvalidConfigurationError(\"Diffraction query is off the site lattice; the object-space convolution does not apply.\");\n }\n const scale = input.metresPerFrameUnit, distance = input.distanceM, baseEvaluate = base.evaluateRadiance;\n const evaluateRadiance = (request: Readonly<SceneRadianceEvaluationRequest>): SceneRadianceEvaluationResult => {\n const result = baseEvaluate.call(base, request), o = (request.target as { outgoingDirectionUnitVector: { x: number; y: number; z: number } }).outgoingDirectionUnitVector;\n const t = distance / -o.z;\n return { ...result, spectralRadianceWattsPerSquareMeterSteradianNanometer: blurredAt(-o.x * t / scale, -o.y * t / scale, request.wavelengthNanometers) };\n };\n // 2.6: the result is the base result with only its radiance replaced (same keys and records), so an engine-built base\n // evaluator keeps its mark (see core/internal-radiance-evaluator.ts).\n if (isInternalSceneRadianceEvaluator(baseEvaluate)) {\n markInternalSceneRadianceEvaluator(evaluateRadiance);\n // #394: its radiance is the convolved value at one lattice site (shift s, lattice column li, row lj) per wavelength, so\n // the lean executor may read it by that key: the same plane point, lattice choice and band value as evaluateRadiance.\n registerInternalRadianceAccess(evaluateRadiance, {\n tabulated: false,\n keyOfDirection(o): number | undefined {\n if (!(-o.z > 0)) return undefined;\n const t = distance / -o.z, u = -o.x * t / scale, v = -o.y * t / scale, fi = u / g - 0.5 + W / 2, fj = -v / g - 0.5 + H / 2;\n for (let s = 0; s < shifts.length; s++) {\n const shift = shifts[s]!, i = Math.round(fi - shift.x), j = Math.round(fj - shift.y);\n if (Math.abs(fi - shift.x - i) > LATTICE_TOLERANCE_SITES || Math.abs(fj - shift.y - j) > LATTICE_TOLERANCE_SITES) continue;\n const li = i + M, lj = j + M;\n if (li < lx0 || lj < ly0 || li >= lx1 || lj >= ly1) return undefined;\n return (s * LH + lj) * LW + li;\n }\n return undefined;\n },\n radianceOfKey(key, nm): number {\n const w = index.get(nm);\n if (w === undefined) throw new InvalidConfigurationError(\"Diffraction query is off the site lattice; the object-space convolution does not apply.\");\n const li = key % LW, rest = (key - li) / LW, lj = rest % LH, s = (rest - lj) / LH;\n return valueAt(s, w, li, lj);\n }\n });\n }\n return {\n sceneId: base.sceneId, providerProfileId: base.providerProfileId, radianceAt: base.radianceAt,\n evaluateRadiance,\n evaluateApertureRadiance(): SceneRadianceEvaluationResult {\n throw new InvalidConfigurationError(\"Diffraction by object-space convolution does not take pupil rays.\");\n }\n };\n}\n\n/** Largest kernel sum, and largest sample, the object-space convolution accepts (as `IRRADIANCE_CONVOLUTION_LIMITS`). */\nconst MAXIMUM_KERNEL_SUM = 1 + 2 ** -20, MAXIMUM_SAMPLE = 2 ** 100;\n\n/** #492: a site kernel of radius R, checked as `calculateIrradianceConvolution` checks its kernels. */\nexport function checkedSiteKernel(kernel: Float64Array, R: number): Float64Array {\n if (!(kernel instanceof Float64Array) || kernel.length !== (2 * R + 1) ** 2) throw new InvalidConfigurationError(\"Site kernels must be (2R + 1)² taps.\");\n let sum = 0;\n for (let k = 0; k < kernel.length; k++) {\n const w = kernel[k]!;\n if (!(w >= 0 && w <= 1)) throw new InvalidConfigurationError(\"Site kernel weights must be finite numbers in [0, 1].\");\n sum += w;\n }\n if (sum > MAXIMUM_KERNEL_SUM) throw new InvalidConfigurationError(\"A PSF kernel may not create energy (sum exceeds 1).\");\n return kernel;\n}\n\n/** #492: the non-zero taps of a kernel as offsets into a grid of `gridWidth` columns (−v·gridWidth − u) and weights, v outer, u inner, ascending. */\nexport function kernelTaps(kernel: Float64Array, R: number, gridWidth: number): { offsets: Int32Array; weights: Float64Array } {\n const offsets: number[] = [], weights: number[] = [];\n for (let v = -R, t = 0; v <= R; v++) for (let u = -R; u <= R; u++, t++) {\n const w = kernel[t]!;\n if (w !== 0) { offsets.push(-v * gridWidth - u); weights.push(w); }\n }\n return { offsets: Int32Array.from(offsets), weights: Float64Array.from(weights) };\n}\n\n/**\n * #492: out(x, y) = Σ_t K(t)·samples(x + R − t_u, y + R − t_v) for the band's own values only (x < width, y < rows): every tap of\n * these lies inside the grid (it holds R extra samples on each side), so no boundary rule applies. Samples are checked as\n * `calculateIrradianceConvolution` checks them.\n */\nexport function gatherInterior(samples: Float64Array, taps: { offsets: Int32Array; weights: Float64Array }, gridWidth: number, width: number, rows: number, R: number): Float64Array {\n checkSamples(samples);\n const { offsets, weights } = taps, count = weights.length, out = new Float64Array(width * rows);\n for (let y = 0; y < rows; y++) {\n const rowBase = (y + R) * gridWidth + R;\n for (let x = 0; x < width; x++) {\n const base = rowBase + x;\n let sum = 0;\n for (let k = 0; k < count; k++) sum += samples[base + offsets[k]!]! * weights[k]!;\n out[y * width + x] = sum;\n }\n }\n return out;\n}\n\n/** Samples are checked as `calculateIrradianceConvolution` checks them. */\nfunction checkSamples(samples: Float64Array): void {\n for (let k = 0; k < samples.length; k++) {\n const v = samples[k]!;\n if (!(v >= 0 && v <= MAXIMUM_SAMPLE)) throw new InvalidConfigurationError(\"Irradiance samples must be finite, non-negative and within the declared magnitude.\");\n }\n}\n\n/**\n * #553: a field-varying site kernel (the cat's eye of `lens.defocus`) as square zones of the native raster, each zone with\n * the kernel of its centre's field point, the same at every spectral node. A piecewise-constant (sectioned) approximation\n * of a space-variant PSF (Denis, Thiébaut, Soulez, Becker and Mourya 2015, \"Fast approximations of shift-variant blur\",\n * International Journal of Computer Vision 115:253–278, §3.1, open preprint arXiv:1502.03305).\n */\nexport interface SiteKernelFieldZones {\n /** Zone side in native sites: zone (zx, zy) holds the native sites [zx·size, (zx + 1)·size) × [zy·size, (zy + 1)·size). */\n size: number;\n columns: number;\n rows: number;\n /** The kernel of zone zy·columns + zx, (2R + 1)² row-major taps with R the provider's `kernelRadius`. */\n kernelOf(zone: number): Float64Array;\n}\n\n/**\n * #553: the band gather with {@link SiteKernelFieldZones}: out(x) = Σ_t K_z(t)·samples(x − t), z the zone of output site x\n * (its native site, clamped to the raster for the margins of offset lattices). Each value is summed over its zone's taps in\n * the order of {@link gatherInterior} (v outer, u inner, ascending), so a zoned gather whose zones all hold one kernel gives\n * gatherInterior's bits. The zones' taps are built on first use and the last 3 rows of zones kept.\n */\nexport function createZonedGather(zones: SiteKernelFieldZones, R: number, gridWidth: number, nativeWidth: number, nativeHeight: number, margin: number):\n (samples: Float64Array, latticeX0: number, latticeY0: number, width: number, rows: number) => Float64Array {\n const cache = new Map<number, { offsets: Int32Array; weights: Float64Array }>(), capacity = 3 * zones.columns;\n const tapsOf = (zone: number): { offsets: Int32Array; weights: Float64Array } => {\n let taps = cache.get(zone);\n if (taps) { cache.delete(zone); cache.set(zone, taps); return taps; }\n taps = kernelTaps(checkedSiteKernel(zones.kernelOf(zone), R), R, gridWidth);\n cache.set(zone, taps);\n if (cache.size > capacity) cache.delete(cache.keys().next().value!);\n return taps;\n };\n const zoneOf = (lattice: number, extent: number, count: number): number => Math.min(count - 1, Math.floor(Math.min(extent - 1, Math.max(0, lattice - margin)) / zones.size));\n return (samples, latticeX0, latticeY0, width, rows) => {\n checkSamples(samples);\n const out = new Float64Array(width * rows), columnZone = new Int32Array(width);\n for (let x = 0; x < width; x++) columnZone[x] = zoneOf(latticeX0 + x, nativeWidth, zones.columns);\n for (let y = 0; y < rows; y++) {\n const rowBase = (y + R) * gridWidth + R, zoneRow = zoneOf(latticeY0 + y, nativeHeight, zones.rows) * zones.columns;\n let x = 0;\n while (x < width) {\n const zx = columnZone[x]!, { offsets, weights } = tapsOf(zoneRow + zx), count = weights.length;\n for (; x < width && columnZone[x] === zx; x++) {\n const base = rowBase + x;\n let sum = 0;\n for (let k = 0; k < count; k++) sum += samples[base + offsets[k]!]! * weights[k]!;\n out[y * width + x] = sum;\n }\n }\n }\n return out;\n };\n}\n"]}
1
+ {"version":3,"file":"diffraction-provider.js","sourceRoot":"","sources":["../../src/facade/diffraction-provider.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Fast execution of `simulateCapture`'s `lens.diffraction` (2.1): an object-space convolution in the scene\n * provider, instead of one scene query per PSF tap in the environment PSF quadrature.\n *\n * The environment quadrature computes, at each site centre q and spectral node λ,\n * E(q, λ) = Σ_k K_λ(k)·T·L(s_k(q), λ),\n * where s_k(q) is the tap's source point (`sensorPsfSourcePoint`), L the scene radiance at the plane point\n * that source point sees, and T the radiance-to-irradiance factor. For the facade's planar scene seen\n * through the ideal rectilinear projection with a still camera and no lens field mapping, field throughput or\n * pupil rays:\n * - T is the same at every sensor point (paraxial π/(4·N_w²), no cos⁴ term), and\n * - with the kernel sampled on the site pitch, every source point is the centre of another site, so the plane\n * points form one regular lattice: u = (i + ½ − W/2)·2/w, v = −(j + ½ − H/2)·2/w (frame units, native\n * site (i, j), W×H native sites, w output width).\n * So E(q, λ) = T·B(q, λ) with B = K_λ ⊛ L sampled on that lattice: the same sum, in a different floating-point\n * order. B is computed once per spectral node with the engine's isoplanatic convolution\n * (`calculateIrradianceConvolution`, kernels from `resolveLensPsfConvolutionKernels`, exact site sampling) over a\n * grid that holds every source (the native raster plus the kernel radius on each side), in row bands; each band gathers only\n * its own values, the grid's interior (#419, `createIrradianceConvolutionInteriorRunner`: each value bit-identical to\n * `calculateIrradianceConvolution`'s there, without the 2R rows and columns of the band's grid that no query reads). The\n * provider then answers each site-centre query with B instead of L, and the environment request declares no\n * PSF. Incoherent imaging is a linear superposition of intensity PSFs, so convolving radiance on the object\n * plane and convolving irradiance on the image plane agree for a planar object and a space-invariant PSF\n * (MIT OpenCourseWare 2.71, lecture 22, free; also see: Goodman, Introduction to Fourier Optics, 4th ed., §7.1).\n *\n * With an anti-aliasing point-splitting filter (2.1, `sensor.antiAliasing`) the environment queries the PSF taps\n * around each pre-filter source point q − a (a = a split offset) instead of around q. Those taps lie on the site\n * lattice shifted by a, so the same argument holds on each shifted lattice: B is computed once per distinct\n * fractional shift (offsets that differ by whole sites share one lattice; the centred four-spot filter with a\n * one-site separation needs a single half-site-shifted lattice) over the native raster widened by the largest\n * offset, and the environment's spatial quadrature still forms the weighted split sum.\n *\n * Region renders (2.6, `window`): only the lattice rows and columns that the region's sites can query (the window\n * plus the largest offset on each side) are convolved, over a grid that adds the kernel radius on each side. Every\n * output value is the same gather as in the whole render: the grid always holds every tap of every value it keeps\n * (real scene radiance out to the kernel radius, never a truncated edge), the single kernel patch does not depend on\n * the grid's origin, and the gather (`convolveIrradianceRows`, and its interior form) sums each value in a fixed tap order (v outer, u inner). Narrowing\n * the grid therefore removes only values that no query reads, and the kept values are bit-identical.\n *\n * A query that does not land on one of the lattices (within 1e-6 site) is refused rather than approximated: the\n * facade uses this path only when the lattice argument above holds. A query outside the window is refused too.\n *\n * Defocus (#492, `lens.defocus`): the same argument holds for any space-invariant kernel on the site lattice, so the facade\n * passes `siteKernels` instead (the geometric defocus disc, or each node's diffraction kernel convolved with it). Their radius\n * may exceed the public 32-site convolution limit, so this path does not call `calculateIrradianceConvolution`: it checks the\n * samples and the kernel sums as that function does and gathers only the band's own values (`gatherInterior`), each summed\n * over the taps in the same fixed order (v outer, u inner, ascending; zero taps skipped, which adds exact zeros only). Like\n * the diffraction path (#419), it does not compute the 2R grid rows and columns around a band.\n *\n * Large defocus kernels (#564, `largeKernel`): above 64 sites the disc is convolved by runs in fixed tiles instead of bands\n * (`large-defocus-lattice.ts`, `site-kernel-runs.ts`), each node's diffraction kernel after it; the plane points and the\n * material lookup are the bands' own, and values stay independent of the window.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { isInternalSceneRadianceEvaluator, markInternalSceneRadianceEvaluator, registerInternalRadianceAccess } from \"../core/internal-radiance-evaluator.js\";\nimport type { SceneRadianceEvaluationRequest, SceneRadianceEvaluationResult } from \"../schema/scene-radiance.js\";\nimport { createIrradianceConvolutionInteriorRunner } from \"../optics/irradiance-convolution.js\";\nimport { loadedKit, qualityKit } from \"./on-demand-kits.js\";\nimport type { ResolveLensSampledPsfInput } from \"../optics/lens-psf-profile.js\";\nimport type { PlanarSceneRadianceProvider } from \"./scene-radiance.js\";\nimport type { LargeDefocusKernel, LargeDefocusNodeLattice } from \"./large-defocus-lattice.js\";\n\n/** Rows of native sites per convolution band, and the bands kept. Banding changes memory only, never values. */\nconst BAND_ROWS = 32;\nconst CACHED_BANDS = 4;\nconst LATTICE_TOLERANCE_SITES = 1e-6;\n\nexport interface DiffractedPlanarProviderInput {\n base: PlanarSceneRadianceProvider;\n /** The optical state of the sampled PSF, as for `resolveLensSampledPsf`, without field point and wavelength. Unused with `siteKernels`. */\n psf?: Omit<ResolveLensSampledPsfInput, \"fieldPointMm\" | \"wavelengthNm\">;\n /**\n * #492: the kernel of each spectral node on the site lattice, (2·kernelRadius + 1)² taps in row-major order, applied\n * instead of the diffraction kernels of `psf` (the defocus disc, or each node's diffraction kernel convolved with it).\n * Any radius; each kernel's sum may not exceed 1 + 2^-20.\n */\n siteKernels?: (wavelengthNm: number) => Float64Array;\n /** Spectral nodes the environment queries (the profile's wavelength nodes). */\n wavelengthsNm: readonly number[];\n kernelRadius: number;\n nativeWidth: number;\n nativeHeight: number;\n /** Output (active) width in sites: frame units are 2/outputWidth per site. */\n outputWidth: number;\n sitePitchMicrometers: number;\n /** Planar geometry of the base provider, to map query directions to plane points exactly as it does. */\n distanceM: number;\n metresPerFrameUnit: number;\n /**\n * Offsets of the query points from the site centres, in sites (+x right, +y down): the anti-aliasing split\n * offsets with their sign reversed (the environment queries q − a). Default: one zero offset.\n */\n queryOffsetsSites?: readonly { x: number; y: number }[];\n /**\n * Region renders (2.6): the native sites that will be queried (x, y, width, height in the native raster). Only the\n * lattice they can reach is convolved; values are bit-identical to the whole render's. Default: the whole raster.\n */\n window?: { x: number; y: number; width: number; height: number };\n /** Called with the duration in ms of each band convolution (diagnostics only; never changes values). */\n onConvolution?: (milliseconds: number) => void;\n /**\n * #564: a defocus kernel above the direct radius, convolved by runs in fixed tiles (`large-defocus-lattice.ts`), with each\n * node's diffraction kernel after it; used instead of `siteKernels` and `psf` (`kernelRadius` is then unused).\n */\n largeKernel?: LargeDefocusKernel;\n /** #553: a field-varying kernel by zones (the cat's eye), used instead of `siteKernels` in the gather; needs `siteKernels`. */\n fieldZones?: SiteKernelFieldZones;\n}\n\n/** Internal (not exported from the package): the base provider with diffraction applied as an object-space convolution. */\nexport function createDiffractedPlanarProvider(input: DiffractedPlanarProviderInput): PlanarSceneRadianceProvider {\n const { base, wavelengthsNm, nativeWidth: W, nativeHeight: H, kernelRadius: R } = input;\n const g = 2 / input.outputWidth, pitch = input.sitePitchMicrometers;\n const index = new Map(wavelengthsNm.map((nm, i) => [nm, i]));\n // One lattice per distinct fractional query offset; M extra sites per side hold the offset queries.\n const offsets = input.queryOffsetsSites ?? [{ x: 0, y: 0 }];\n const fraction = (value: number): number => { const f = value - Math.floor(value); return f > 1 - LATTICE_TOLERANCE_SITES ? 0 : f < LATTICE_TOLERANCE_SITES ? 0 : f; };\n const shifts: { x: number; y: number }[] = [];\n for (const o of offsets) {\n const f = { x: fraction(o.x), y: fraction(o.y) };\n if (!shifts.some((s) => Math.abs(s.x - f.x) <= LATTICE_TOLERANCE_SITES && Math.abs(s.y - f.y) <= LATTICE_TOLERANCE_SITES)) shifts.push(f);\n }\n const M = Math.max(0, ...offsets.map((o) => Math.ceil(Math.max(Math.abs(o.x), Math.abs(o.y)) - LATTICE_TOLERANCE_SITES)));\n const LW = W + 2 * M, LH = H + 2 * M;\n // Lattice window (indices i + M, j + M): the sites the region queries plus the largest offset on each side, clipped\n // to the lattice. A site i queries i + floor(offset), and floor(offset) lies in [-M, M].\n const win = input.window ?? { x: 0, y: 0, width: W, height: H };\n const lx0 = Math.max(0, win.x), lx1 = Math.min(LW, win.x + win.width + 2 * M);\n const ly0 = Math.max(0, win.y), ly1 = Math.min(LH, win.y + win.height + 2 * M);\n if (!(lx0 < lx1 && ly0 < ly1)) throw new InvalidConfigurationError(\"Diffraction window must overlap the native raster.\");\n const NW = lx1 - lx0;\n // One kernel per wavelength, on the site grid, from the engine's own tap-to-site mapping (field point 0, 0); kept across calls.\n const siteKernels = input.siteKernels, large = input.largeKernel;\n if (!siteKernels && !input.psf && !large) throw new InvalidConfigurationError(\"The object-space convolution needs a PSF or site kernels.\");\n const kernels = large ? [] : wavelengthsNm.map((wavelengthNm) => siteKernels ? checkedSiteKernel(siteKernels(wavelengthNm), R) :\n loadedKit(qualityKit).siteDiffractionKernel(input.psf!, wavelengthNm, pitch, R, \"Diffraction kernels must sample the site pitch exactly.\"));\n // #492: each site kernel's non-zero taps as grid offsets, in the gather's order.\n const taps = siteKernels && !large ? kernels.map((kernel) => kernelTaps(kernel, R, NW + 2 * R)) : [];\n const gridWidth = NW + 2 * R;\n const zonedGather = input.fieldZones && siteKernels ? createZonedGather(input.fieldZones, R, gridWidth, W, H, M) : undefined;\n const now = (): number => globalThis.performance?.now() ?? Date.now();\n const bands = new Map<number, Float64Array[][]>();\n const materialAt = base.chartMaterialAt?.bind(base), materialRadiance = base.materialRadiance?.bind(base);\n function band(b: number): Float64Array[][] {\n const cached = bands.get(b);\n if (cached) { bands.delete(b); bands.set(b, cached); return cached; }\n const started = input.onConvolution ? now() : 0;\n const y0 = ly0 + b * BAND_ROWS, rows = Math.min(BAND_ROWS, ly1 - y0), gridHeight = rows + 2 * R, size = gridWidth * gridHeight;\n // #453: the band's shifts × spectral nodes convolutions share one geometry, validated once (the first with every check of\n // calculateIrradianceConvolution; every later one still checks its samples and kernel). #419: only the band's own rows × NW\n // values are gathered (the grid's interior), each bit-identical to calculateIrradianceConvolution's value there.\n const convolve = siteKernels ? undefined : createIrradianceConvolutionInteriorRunner({ schemaVersion: \"0.1.0\", width: gridWidth, height: gridHeight, kernelRadius: R,\n patchWidth: gridWidth, patchHeight: gridHeight, boundary: \"zero-outside-grid\" });\n const values = shifts.map((shift) => {\n // The plane point of lattice grid sample (gx, gy) of this shift, the same expressions for both fills below.\n const vOf = (gy: number): number => shift.y === 0 ? -(y0 + gy - R - M + 0.5 - H / 2) * g : -(y0 + gy - R - M + 0.5 + shift.y - H / 2) * g;\n const uOf = (x: number): number => shift.x === 0 ? (x - R - M + 0.5 - W / 2) * g : (x - R - M + 0.5 + shift.x - W / 2) * g;\n // #453, material scenes (chart presets and caller material scenes): radianceAt(u, v, nm) is materialRadiance(chartMaterialAt(u, v), nm)\n // (scene-radiance.ts), so the material is looked up once per lattice point and each node's samples come from one\n // materialRadiance per material present, the same numbers as one radianceAt per point and node.\n let materialOf: Int32Array | undefined;\n if (materialAt && materialRadiance) {\n materialOf = new Int32Array(size);\n for (let gy = 0; gy < gridHeight; gy++) {\n const v = vOf(gy);\n for (let gx = 0, x = lx0; gx < gridWidth; gx++, x++) materialOf[gy * gridWidth + gx] = materialAt(uOf(x), v);\n }\n }\n return wavelengthsNm.map((nm, w) => {\n const samples = new Float64Array(size);\n if (materialOf) {\n const radiance = new Map<number, number>();\n for (let i = 0; i < size; i++) {\n const m = materialOf[i]!;\n let value = radiance.get(m);\n if (value === undefined) { value = materialRadiance!(m, nm); radiance.set(m, value); }\n samples[i] = value;\n }\n } else {\n for (let gy = 0; gy < gridHeight; gy++) {\n const v = vOf(gy);\n for (let gx = 0, x = lx0; gx < gridWidth; gx++, x++) samples[gy * gridWidth + gx] = base.radianceAt(uOf(x), v, nm);\n }\n }\n if (zonedGather) return zonedGather(samples, lx0, y0, NW, rows);\n if (!convolve) return gatherInterior(samples, taps[w]!, gridWidth, NW, rows, R);\n return convolve(samples, kernels[w]!);\n });\n });\n bands.set(b, values);\n if (bands.size > CACHED_BANDS) bands.delete(bands.keys().next().value!);\n if (input.onConvolution) input.onConvolution(now() - started);\n return values;\n }\n // #564: one run lattice per shift (lattice points li, lj), its samples the base radiance at the same plane points as the bands'.\n const largeLattices: (LargeDefocusNodeLattice | undefined)[] = [];\n function largeLattice(s: number): LargeDefocusNodeLattice {\n let lattice = largeLattices[s];\n if (!lattice) {\n const shift = shifts[s]!;\n const vOf = (lj: number): number => shift.y === 0 ? -(lj - M + 0.5 - H / 2) * g : -(lj - M + 0.5 + shift.y - H / 2) * g;\n const uOf = (li: number): number => shift.x === 0 ? (li - M + 0.5 - W / 2) * g : (li - M + 0.5 + shift.x - W / 2) * g;\n const kit = loadedKit(qualityKit);\n lattice = largeLattices[s] = kit.createLargeDefocusNodeLattice({ kernel: large!, wavelengthsNm, capacityBytes: kit.LARGE_DEFOCUS_CACHE_BYTES / shifts.length, ...(input.onConvolution ? { onTile: input.onConvolution } : {}),\n source: (x0, y0, width, height) => {\n const size = width * height;\n let materialOf: Int32Array | undefined;\n if (materialAt && materialRadiance) {\n materialOf = new Int32Array(size);\n for (let y = 0; y < height; y++) { const v = vOf(y0 + y); for (let x = 0; x < width; x++) materialOf[y * width + x] = materialAt(uOf(x0 + x), v); }\n }\n return (node: number): Float64Array => {\n const nm = wavelengthsNm[node]!, samples = new Float64Array(size);\n if (materialOf) {\n const radiance = new Map<number, number>();\n for (let k = 0; k < size; k++) {\n const m = materialOf[k]!;\n let value = radiance.get(m);\n if (value === undefined) { value = materialRadiance!(m, nm); radiance.set(m, value); }\n samples[k] = value;\n }\n } else for (let y = 0; y < height; y++) { const v = vOf(y0 + y); for (let x = 0; x < width; x++) samples[y * width + x] = base.radianceAt(uOf(x0 + x), v, nm); }\n return samples;\n };\n } });\n }\n return lattice;\n }\n /** The convolved value of shift s, node index w, at lattice point (li, lj) inside the window. */\n function valueAt(s: number, w: number, li: number, lj: number): number {\n return large ? largeLattice(s).valueAt(w, li, lj) : band(Math.floor((lj - ly0) / BAND_ROWS))[s]![w]![((lj - ly0) % BAND_ROWS) * NW + li - lx0]!;\n }\n function blurredAt(u: number, v: number, nm: number): number {\n const w = index.get(nm), fi = u / g - 0.5 + W / 2, fj = -v / g - 0.5 + H / 2;\n if (w !== undefined) for (let s = 0; s < shifts.length; s++) {\n const shift = shifts[s]!, i = Math.round(fi - shift.x), j = Math.round(fj - shift.y);\n if (Math.abs(fi - shift.x - i) > LATTICE_TOLERANCE_SITES || Math.abs(fj - shift.y - j) > LATTICE_TOLERANCE_SITES) continue;\n const li = i + M, lj = j + M;\n if (li < lx0 || lj < ly0 || li >= lx1 || lj >= ly1) break;\n return valueAt(s, w, li, lj);\n }\n throw new InvalidConfigurationError(\"Diffraction query is off the site lattice; the object-space convolution does not apply.\");\n }\n const scale = input.metresPerFrameUnit, distance = input.distanceM, baseEvaluate = base.evaluateRadiance;\n const evaluateRadiance = (request: Readonly<SceneRadianceEvaluationRequest>): SceneRadianceEvaluationResult => {\n const result = baseEvaluate.call(base, request), o = (request.target as { outgoingDirectionUnitVector: { x: number; y: number; z: number } }).outgoingDirectionUnitVector;\n const t = distance / -o.z;\n return { ...result, spectralRadianceWattsPerSquareMeterSteradianNanometer: blurredAt(-o.x * t / scale, -o.y * t / scale, request.wavelengthNanometers) };\n };\n // 2.6: the result is the base result with only its radiance replaced (same keys and records), so an engine-built base\n // evaluator keeps its mark (see core/internal-radiance-evaluator.ts).\n if (isInternalSceneRadianceEvaluator(baseEvaluate)) {\n markInternalSceneRadianceEvaluator(evaluateRadiance);\n // #394: its radiance is the convolved value at one lattice site (shift s, lattice column li, row lj) per wavelength, so\n // the lean executor may read it by that key: the same plane point, lattice choice and band value as evaluateRadiance.\n registerInternalRadianceAccess(evaluateRadiance, {\n tabulated: false,\n keyOfDirection(o): number | undefined {\n if (!(-o.z > 0)) return undefined;\n const t = distance / -o.z, u = -o.x * t / scale, v = -o.y * t / scale, fi = u / g - 0.5 + W / 2, fj = -v / g - 0.5 + H / 2;\n for (let s = 0; s < shifts.length; s++) {\n const shift = shifts[s]!, i = Math.round(fi - shift.x), j = Math.round(fj - shift.y);\n if (Math.abs(fi - shift.x - i) > LATTICE_TOLERANCE_SITES || Math.abs(fj - shift.y - j) > LATTICE_TOLERANCE_SITES) continue;\n const li = i + M, lj = j + M;\n if (li < lx0 || lj < ly0 || li >= lx1 || lj >= ly1) return undefined;\n return (s * LH + lj) * LW + li;\n }\n return undefined;\n },\n radianceOfKey(key, nm): number {\n const w = index.get(nm);\n if (w === undefined) throw new InvalidConfigurationError(\"Diffraction query is off the site lattice; the object-space convolution does not apply.\");\n const li = key % LW, rest = (key - li) / LW, lj = rest % LH, s = (rest - lj) / LH;\n return valueAt(s, w, li, lj);\n }\n });\n }\n return {\n sceneId: base.sceneId, providerProfileId: base.providerProfileId, radianceAt: base.radianceAt,\n evaluateRadiance,\n evaluateApertureRadiance(): SceneRadianceEvaluationResult {\n throw new InvalidConfigurationError(\"Diffraction by object-space convolution does not take pupil rays.\");\n }\n };\n}\n\n/** Largest kernel sum, and largest sample, the object-space convolution accepts (as `IRRADIANCE_CONVOLUTION_LIMITS`). */\nconst MAXIMUM_KERNEL_SUM = 1 + 2 ** -20, MAXIMUM_SAMPLE = 2 ** 100;\n\n/** #492: a site kernel of radius R, checked as `calculateIrradianceConvolution` checks its kernels. */\nexport function checkedSiteKernel(kernel: Float64Array, R: number): Float64Array {\n if (!(kernel instanceof Float64Array) || kernel.length !== (2 * R + 1) ** 2) throw new InvalidConfigurationError(\"Site kernels must be (2R + 1)² taps.\");\n let sum = 0;\n for (let k = 0; k < kernel.length; k++) {\n const w = kernel[k]!;\n if (!(w >= 0 && w <= 1)) throw new InvalidConfigurationError(\"Site kernel weights must be finite numbers in [0, 1].\");\n sum += w;\n }\n if (sum > MAXIMUM_KERNEL_SUM) throw new InvalidConfigurationError(\"A PSF kernel may not create energy (sum exceeds 1).\");\n return kernel;\n}\n\n/** #492: the non-zero taps of a kernel as offsets into a grid of `gridWidth` columns (−v·gridWidth − u) and weights, v outer, u inner, ascending. */\nexport function kernelTaps(kernel: Float64Array, R: number, gridWidth: number): { offsets: Int32Array; weights: Float64Array } {\n const offsets: number[] = [], weights: number[] = [];\n for (let v = -R, t = 0; v <= R; v++) for (let u = -R; u <= R; u++, t++) {\n const w = kernel[t]!;\n if (w !== 0) { offsets.push(-v * gridWidth - u); weights.push(w); }\n }\n return { offsets: Int32Array.from(offsets), weights: Float64Array.from(weights) };\n}\n\n/**\n * #492: out(x, y) = Σ_t K(t)·samples(x + R − t_u, y + R − t_v) for the band's own values only (x < width, y < rows): every tap of\n * these lies inside the grid (it holds R extra samples on each side), so no boundary rule applies. Samples are checked as\n * `calculateIrradianceConvolution` checks them.\n */\nexport function gatherInterior(samples: Float64Array, taps: { offsets: Int32Array; weights: Float64Array }, gridWidth: number, width: number, rows: number, R: number): Float64Array {\n checkSamples(samples);\n const { offsets, weights } = taps, count = weights.length, out = new Float64Array(width * rows);\n for (let y = 0; y < rows; y++) {\n const rowBase = (y + R) * gridWidth + R;\n for (let x = 0; x < width; x++) {\n const base = rowBase + x;\n let sum = 0;\n for (let k = 0; k < count; k++) sum += samples[base + offsets[k]!]! * weights[k]!;\n out[y * width + x] = sum;\n }\n }\n return out;\n}\n\n/** Samples are checked as `calculateIrradianceConvolution` checks them. */\nfunction checkSamples(samples: Float64Array): void {\n for (let k = 0; k < samples.length; k++) {\n const v = samples[k]!;\n if (!(v >= 0 && v <= MAXIMUM_SAMPLE)) throw new InvalidConfigurationError(\"Irradiance samples must be finite, non-negative and within the declared magnitude.\");\n }\n}\n\n/**\n * #553: a field-varying site kernel (the cat's eye of `lens.defocus`) as square zones of the native raster, each zone with\n * the kernel of its centre's field point, the same at every spectral node. A piecewise-constant (sectioned) approximation\n * of a space-variant PSF (Denis, Thiébaut, Soulez, Becker and Mourya 2015, \"Fast approximations of shift-variant blur\",\n * International Journal of Computer Vision 115:253–278, §3.1, open preprint arXiv:1502.03305).\n */\nexport interface SiteKernelFieldZones {\n /** Zone side in native sites: zone (zx, zy) holds the native sites [zx·size, (zx + 1)·size) × [zy·size, (zy + 1)·size). */\n size: number;\n columns: number;\n rows: number;\n /** The kernel of zone zy·columns + zx, (2R + 1)² row-major taps with R the provider's `kernelRadius`. */\n kernelOf(zone: number): Float64Array;\n}\n\n/**\n * #553: the band gather with {@link SiteKernelFieldZones}: out(x) = Σ_t K_z(t)·samples(x − t), z the zone of output site x\n * (its native site, clamped to the raster for the margins of offset lattices). Each value is summed over its zone's taps in\n * the order of {@link gatherInterior} (v outer, u inner, ascending), so a zoned gather whose zones all hold one kernel gives\n * gatherInterior's bits. The zones' taps are built on first use and the last 3 rows of zones kept.\n */\nexport function createZonedGather(zones: SiteKernelFieldZones, R: number, gridWidth: number, nativeWidth: number, nativeHeight: number, margin: number):\n (samples: Float64Array, latticeX0: number, latticeY0: number, width: number, rows: number) => Float64Array {\n const cache = new Map<number, { offsets: Int32Array; weights: Float64Array }>(), capacity = 3 * zones.columns;\n const tapsOf = (zone: number): { offsets: Int32Array; weights: Float64Array } => {\n let taps = cache.get(zone);\n if (taps) { cache.delete(zone); cache.set(zone, taps); return taps; }\n taps = kernelTaps(checkedSiteKernel(zones.kernelOf(zone), R), R, gridWidth);\n cache.set(zone, taps);\n if (cache.size > capacity) cache.delete(cache.keys().next().value!);\n return taps;\n };\n const zoneOf = (lattice: number, extent: number, count: number): number => Math.min(count - 1, Math.floor(Math.min(extent - 1, Math.max(0, lattice - margin)) / zones.size));\n return (samples, latticeX0, latticeY0, width, rows) => {\n checkSamples(samples);\n const out = new Float64Array(width * rows), columnZone = new Int32Array(width);\n for (let x = 0; x < width; x++) columnZone[x] = zoneOf(latticeX0 + x, nativeWidth, zones.columns);\n for (let y = 0; y < rows; y++) {\n const rowBase = (y + R) * gridWidth + R, zoneRow = zoneOf(latticeY0 + y, nativeHeight, zones.rows) * zones.columns;\n let x = 0;\n while (x < width) {\n const zx = columnZone[x]!, { offsets, weights } = tapsOf(zoneRow + zx), count = weights.length;\n for (; x < width && columnZone[x] === zx; x++) {\n const base = rowBase + x;\n let sum = 0;\n for (let k = 0; k < count; k++) sum += samples[base + offsets[k]!]! * weights[k]!;\n out[y * width + x] = sum;\n }\n }\n }\n return out;\n };\n}\n"]}