@photivra/engine 2.18.0 → 2.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (335) hide show
  1. package/CHANGELOG.md +179 -1
  2. package/CITATION.cff +1 -1
  3. package/NODE_SUPPORT.md +7 -5
  4. package/README.md +6 -6
  5. package/SECURITY.md +1 -1
  6. package/THIRD_PARTY.md +14 -10
  7. package/dist/capture/dng-lens-correction-opcodes.d.ts +32 -0
  8. package/dist/capture/dng-lens-correction-opcodes.js +119 -0
  9. package/dist/capture/dng-lens-correction-opcodes.js.map +1 -0
  10. package/dist/capture/focus-control.js +2 -75
  11. package/dist/capture/focus-control.js.map +1 -1
  12. package/dist/capture/native-environment-lean.d.ts +1 -0
  13. package/dist/capture/native-environment-lean.js +2 -6
  14. package/dist/capture/native-environment-lean.js.map +1 -1
  15. package/dist/capture/native-environment-optical-stage.d.ts +1 -0
  16. package/dist/capture/native-environment-optical-stage.js +2 -5
  17. package/dist/capture/native-environment-optical-stage.js.map +1 -1
  18. package/dist/capture/native-environment-raw.js +1 -5
  19. package/dist/capture/native-environment-raw.js.map +1 -1
  20. package/dist/capture/native-raw-dng.d.ts +6 -0
  21. package/dist/capture/native-raw-dng.js +16 -2
  22. package/dist/capture/native-raw-dng.js.map +1 -1
  23. package/dist/capture/release-sequence.js +2 -47
  24. package/dist/capture/release-sequence.js.map +1 -1
  25. package/dist/capture/sensor-raw-producer.js +3 -5
  26. package/dist/capture/sensor-raw-producer.js.map +1 -1
  27. package/dist/color/white-balance.d.ts +2 -0
  28. package/dist/color/white-balance.js +3 -56
  29. package/dist/color/white-balance.js.map +1 -1
  30. package/dist/composition/image-formation-plan.d.ts +1 -0
  31. package/dist/composition/image-formation-plan.js +3 -49
  32. package/dist/composition/image-formation-plan.js.map +1 -1
  33. package/dist/core/evidence-provenance.js +1 -16
  34. package/dist/core/evidence-provenance.js.map +1 -1
  35. package/dist/core/record-validation.d.ts +54 -0
  36. package/dist/core/record-validation.js +176 -0
  37. package/dist/core/record-validation.js.map +1 -1
  38. package/dist/core/scientific-assurance.js +1 -18
  39. package/dist/core/scientific-assurance.js.map +1 -1
  40. package/dist/core/shared-helpers.d.ts +35 -0
  41. package/dist/core/shared-helpers.js +38 -0
  42. package/dist/core/shared-helpers.js.map +1 -0
  43. package/dist/core/spectral-composition.js +1 -36
  44. package/dist/core/spectral-composition.js.map +1 -1
  45. package/dist/core/spectral.js +1 -19
  46. package/dist/core/spectral.js.map +1 -1
  47. package/dist/core/version.d.ts +1 -1
  48. package/dist/core/version.js +1 -1
  49. package/dist/core/version.js.map +1 -1
  50. package/dist/equipment/exposure-capabilities.d.ts +1 -0
  51. package/dist/equipment/exposure-capabilities.js +2 -36
  52. package/dist/equipment/exposure-capabilities.js.map +1 -1
  53. package/dist/equipment/generic-lens-catalogue.d.ts +8 -2
  54. package/dist/equipment/generic-lens-catalogue.js +31 -2
  55. package/dist/equipment/generic-lens-catalogue.js.map +1 -1
  56. package/dist/equipment/generic-tier-assets.js +2 -3
  57. package/dist/equipment/generic-tier-assets.js.map +1 -1
  58. package/dist/equipment/generic-tier-presets.js +2 -3
  59. package/dist/equipment/generic-tier-presets.js.map +1 -1
  60. package/dist/equipment/iso-capabilities.js +2 -49
  61. package/dist/equipment/iso-capabilities.js.map +1 -1
  62. package/dist/equipment/metering-capabilities.js +1 -26
  63. package/dist/equipment/metering-capabilities.js.map +1 -1
  64. package/dist/equipment/release-capabilities.js +1 -53
  65. package/dist/equipment/release-capabilities.js.map +1 -1
  66. package/dist/exposure/auto-iso-slowest-shutter.js +1 -7
  67. package/dist/exposure/auto-iso-slowest-shutter.js.map +1 -1
  68. package/dist/exposure/exposure-duration-control.js +1 -16
  69. package/dist/exposure/exposure-duration-control.js.map +1 -1
  70. package/dist/exposure/exposure-mode-resolver.js +1 -17
  71. package/dist/exposure/exposure-mode-resolver.js.map +1 -1
  72. package/dist/exposure/filtered-exposure-time.d.ts +93 -0
  73. package/dist/exposure/filtered-exposure-time.js +129 -0
  74. package/dist/exposure/filtered-exposure-time.js.map +1 -0
  75. package/dist/exposure/flash-ttl.d.ts +1 -0
  76. package/dist/exposure/flash-ttl.js +1 -1
  77. package/dist/exposure/flash-ttl.js.map +1 -1
  78. package/dist/exposure/flash.js +1 -49
  79. package/dist/exposure/flash.js.map +1 -1
  80. package/dist/exposure/metering-scene-radiance.js +1 -25
  81. package/dist/exposure/metering-scene-radiance.js.map +1 -1
  82. package/dist/exposure/metering-target.js +1 -30
  83. package/dist/exposure/metering-target.js.map +1 -1
  84. package/dist/exposure/metering-temporal.js +1 -8
  85. package/dist/exposure/metering-temporal.js.map +1 -1
  86. package/dist/exposure/metering.js +1 -72
  87. package/dist/exposure/metering.js.map +1 -1
  88. package/dist/exposure/program-line.js +1 -45
  89. package/dist/exposure/program-line.js.map +1 -1
  90. package/dist/facade/develop-joined-parts.d.ts +29 -0
  91. package/dist/facade/develop-joined-parts.js +33 -0
  92. package/dist/facade/develop-joined-parts.js.map +1 -0
  93. package/dist/facade/display-view-gpu.d.ts +7 -4
  94. package/dist/facade/display-view-gpu.js +4 -4
  95. package/dist/facade/display-view-gpu.js.map +1 -1
  96. package/dist/facade/display-view-lens-signal.d.ts +1 -1
  97. package/dist/facade/display-view-lens-signal.js +5 -3
  98. package/dist/facade/display-view-lens-signal.js.map +1 -1
  99. package/dist/facade/display-view.d.ts +3 -1
  100. package/dist/facade/display-view.js +1 -1
  101. package/dist/facade/display-view.js.map +1 -1
  102. package/dist/facade/fast-methods.d.ts +50 -0
  103. package/dist/facade/fast-methods.js +50 -0
  104. package/dist/facade/fast-methods.js.map +1 -0
  105. package/dist/facade/fast-resolution.d.ts +12 -0
  106. package/dist/facade/fast-resolution.js +18 -0
  107. package/dist/facade/fast-resolution.js.map +1 -0
  108. package/dist/facade/generic-lens-capture.d.ts +6 -3
  109. package/dist/facade/generic-lens-capture.js +6 -3
  110. package/dist/facade/generic-lens-capture.js.map +1 -1
  111. package/dist/facade/simulate-capture.d.ts +88 -16
  112. package/dist/facade/simulate-capture.js +279 -153
  113. package/dist/facade/simulate-capture.js.map +1 -1
  114. package/dist/facade/simulate-display-view.d.ts +3 -2
  115. package/dist/facade/simulate-display-view.js +22 -12
  116. package/dist/facade/simulate-display-view.js.map +1 -1
  117. package/dist/gpu/chart-composite-gpu.js +1 -3
  118. package/dist/gpu/chart-composite-gpu.js.map +1 -1
  119. package/dist/gpu/chart-radiance-gpu.js +1 -5
  120. package/dist/gpu/chart-radiance-gpu.js.map +1 -1
  121. package/dist/gpu/display-view-quality-gpu.d.ts +13 -1
  122. package/dist/gpu/display-view-quality-gpu.js +4 -8
  123. package/dist/gpu/display-view-quality-gpu.js.map +1 -1
  124. package/dist/gpu/display-view-speed-gpu.js +3 -25
  125. package/dist/gpu/display-view-speed-gpu.js.map +1 -1
  126. package/dist/gpu/sensor-stage-gpu.js +1 -5
  127. package/dist/gpu/sensor-stage-gpu.js.map +1 -1
  128. package/dist/gpu/webgpu-runtime.d.ts +2 -0
  129. package/dist/gpu/webgpu-runtime.js +3 -0
  130. package/dist/gpu/webgpu-runtime.js.map +1 -1
  131. package/dist/index.d.ts +11 -1
  132. package/dist/index.js +8 -0
  133. package/dist/index.js.map +1 -1
  134. package/dist/motion/camera-rotation.js +1 -6
  135. package/dist/motion/camera-rotation.js.map +1 -1
  136. package/dist/motion/capture-rotation-inverse-mapping.d.ts +12 -0
  137. package/dist/motion/capture-rotation-inverse-mapping.js +2 -2
  138. package/dist/motion/capture-rotation-inverse-mapping.js.map +1 -1
  139. package/dist/motion/capture-rotation-temporal-quadrature.d.ts +1 -0
  140. package/dist/motion/capture-rotation-temporal-quadrature.js +1 -1
  141. package/dist/motion/capture-rotation-temporal-quadrature.js.map +1 -1
  142. package/dist/motion/capture-rotation-trajectory.js +2 -17
  143. package/dist/motion/capture-rotation-trajectory.js.map +1 -1
  144. package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts +1 -0
  145. package/dist/motion/capture-translation-parallax-temporal-quadrature.js +3 -14
  146. package/dist/motion/capture-translation-parallax-temporal-quadrature.js.map +1 -1
  147. package/dist/motion/extended-object-projection.js +5 -40
  148. package/dist/motion/extended-object-projection.js.map +1 -1
  149. package/dist/optics/aperture-diameter.d.ts +47 -0
  150. package/dist/optics/aperture-diameter.js +50 -0
  151. package/dist/optics/aperture-diameter.js.map +1 -0
  152. package/dist/optics/atmospheric-haze.js +1 -7
  153. package/dist/optics/atmospheric-haze.js.map +1 -1
  154. package/dist/optics/brown-conrady-distortion.js +1 -7
  155. package/dist/optics/brown-conrady-distortion.js.map +1 -1
  156. package/dist/optics/complex-pupil-psf.d.ts +1 -0
  157. package/dist/optics/complex-pupil-psf.js +2 -84
  158. package/dist/optics/complex-pupil-psf.js.map +1 -1
  159. package/dist/optics/detail-limit.d.ts +182 -0
  160. package/dist/optics/detail-limit.js +336 -0
  161. package/dist/optics/detail-limit.js.map +1 -0
  162. package/dist/optics/focus-state.js +1 -11
  163. package/dist/optics/focus-state.js.map +1 -1
  164. package/dist/optics/front-of-lens-filter.d.ts +5 -0
  165. package/dist/optics/front-of-lens-filter.js +3 -65
  166. package/dist/optics/front-of-lens-filter.js.map +1 -1
  167. package/dist/optics/generic-lens-psf.d.ts +18 -2
  168. package/dist/optics/generic-lens-psf.js +25 -2
  169. package/dist/optics/generic-lens-psf.js.map +1 -1
  170. package/dist/optics/generic-nd-filter-presets.d.ts +12 -0
  171. package/dist/optics/generic-nd-filter-presets.js +48 -0
  172. package/dist/optics/generic-nd-filter-presets.js.map +1 -0
  173. package/dist/optics/illumination-vignetting.js +1 -6
  174. package/dist/optics/illumination-vignetting.js.map +1 -1
  175. package/dist/optics/lens-psf-profile.d.ts +4 -1
  176. package/dist/optics/lens-psf-profile.js +12 -111
  177. package/dist/optics/lens-psf-profile.js.map +1 -1
  178. package/dist/optics/longitudinal-chromatic-aberration.js +1 -7
  179. package/dist/optics/longitudinal-chromatic-aberration.js.map +1 -1
  180. package/dist/optics/pupil-vignetting.js +1 -7
  181. package/dist/optics/pupil-vignetting.js.map +1 -1
  182. package/dist/optics/radial-distortion.js +1 -6
  183. package/dist/optics/radial-distortion.js.map +1 -1
  184. package/dist/optics/scene-to-sensor-irradiance.d.ts +13 -0
  185. package/dist/optics/scene-to-sensor-irradiance.js +11 -96
  186. package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
  187. package/dist/optics/stray-light.d.ts +1 -0
  188. package/dist/optics/stray-light.js +1 -1
  189. package/dist/optics/stray-light.js.map +1 -1
  190. package/dist/optics/zernike-wavefront.js +1 -7
  191. package/dist/optics/zernike-wavefront.js.map +1 -1
  192. package/dist/output/capture-geometry.js +1 -8
  193. package/dist/output/capture-geometry.js.map +1 -1
  194. package/dist/output/crop-to-match-focal-length.d.ts +62 -0
  195. package/dist/output/crop-to-match-focal-length.js +63 -0
  196. package/dist/output/crop-to-match-focal-length.js.map +1 -0
  197. package/dist/output/developed-lens-corrections.d.ts +62 -0
  198. package/dist/output/developed-lens-corrections.js +135 -0
  199. package/dist/output/developed-lens-corrections.js.map +1 -0
  200. package/dist/output/generic-lens-corrections.d.ts +5 -7
  201. package/dist/output/generic-lens-corrections.js +11 -10
  202. package/dist/output/generic-lens-corrections.js.map +1 -1
  203. package/dist/output/geometric-transforms.js +1 -4
  204. package/dist/output/geometric-transforms.js.map +1 -1
  205. package/dist/output/lens-corrections.d.ts +12 -2
  206. package/dist/output/lens-corrections.js +22 -7
  207. package/dist/output/lens-corrections.js.map +1 -1
  208. package/dist/output/native-capture-sdr.d.ts +2 -2
  209. package/dist/output/native-capture-sdr.js +3 -2
  210. package/dist/output/native-capture-sdr.js.map +1 -1
  211. package/dist/output/print-contrast-reference.js +1 -1
  212. package/dist/output/print-contrast-reference.js.map +1 -1
  213. package/dist/output/print-size-blur-noise.d.ts +110 -0
  214. package/dist/output/print-size-blur-noise.js +138 -0
  215. package/dist/output/print-size-blur-noise.js.map +1 -0
  216. package/dist/processing/development-detail.d.ts +29 -0
  217. package/dist/processing/development-detail.js +128 -107
  218. package/dist/processing/development-detail.js.map +1 -1
  219. package/dist/schema/illumination-temporal.js +3 -72
  220. package/dist/schema/illumination-temporal.js.map +1 -1
  221. package/dist/schema/illumination.d.ts +1 -0
  222. package/dist/schema/illumination.js +2 -65
  223. package/dist/schema/illumination.js.map +1 -1
  224. package/dist/schema/scene-radiance-temporal.js +2 -14
  225. package/dist/schema/scene-radiance-temporal.js.map +1 -1
  226. package/dist/schema/scene-radiance.js +2 -60
  227. package/dist/schema/scene-radiance.js.map +1 -1
  228. package/dist/schema/validation.d.ts +2 -0
  229. package/dist/schema/validation.js +2 -17
  230. package/dist/schema/validation.js.map +1 -1
  231. package/dist/sensor/accumulated-charge.js +2 -59
  232. package/dist/sensor/accumulated-charge.js.map +1 -1
  233. package/dist/sensor/architecture.js +1 -16
  234. package/dist/sensor/architecture.js.map +1 -1
  235. package/dist/sensor/camera-saturation-capacity.d.ts +1 -0
  236. package/dist/sensor/camera-saturation-capacity.js +3 -55
  237. package/dist/sensor/camera-saturation-capacity.js.map +1 -1
  238. package/dist/sensor/capture-color-sampling-binding.js +1 -26
  239. package/dist/sensor/capture-color-sampling-binding.js.map +1 -1
  240. package/dist/sensor/capture-mode-timing.js +1 -39
  241. package/dist/sensor/capture-mode-timing.js.map +1 -1
  242. package/dist/sensor/capture-mode.js +1 -23
  243. package/dist/sensor/capture-mode.js.map +1 -1
  244. package/dist/sensor/color-sampling.js +1 -26
  245. package/dist/sensor/color-sampling.js.map +1 -1
  246. package/dist/sensor/constant-rate-temporal-integration.js +2 -46
  247. package/dist/sensor/constant-rate-temporal-integration.js.map +1 -1
  248. package/dist/sensor/dark-current.js +2 -45
  249. package/dist/sensor/dark-current.js.map +1 -1
  250. package/dist/sensor/eqe-electron-rate.js +2 -41
  251. package/dist/sensor/eqe-electron-rate.js.map +1 -1
  252. package/dist/sensor/exposure-window.d.ts +7 -0
  253. package/dist/sensor/exposure-window.js +9 -24
  254. package/dist/sensor/exposure-window.js.map +1 -1
  255. package/dist/sensor/iso-gain.js +1 -7
  256. package/dist/sensor/iso-gain.js.map +1 -1
  257. package/dist/sensor/iso-signal-chain.js +1 -43
  258. package/dist/sensor/iso-signal-chain.js.map +1 -1
  259. package/dist/sensor/optical-stack.js +1 -25
  260. package/dist/sensor/optical-stack.js.map +1 -1
  261. package/dist/sensor/photon-energy.js +1 -26
  262. package/dist/sensor/photon-energy.js.map +1 -1
  263. package/dist/sensor/physical-charge-capacity.js +3 -77
  264. package/dist/sensor/physical-charge-capacity.js.map +1 -1
  265. package/dist/sensor/radiometry-readiness.js +2 -23
  266. package/dist/sensor/radiometry-readiness.js.map +1 -1
  267. package/dist/sensor/raw-readout.d.ts +3 -0
  268. package/dist/sensor/raw-readout.js +4 -66
  269. package/dist/sensor/raw-readout.js.map +1 -1
  270. package/dist/sensor/raw-reconstruction.js +2 -64
  271. package/dist/sensor/raw-reconstruction.js.map +1 -1
  272. package/dist/sensor/readout-exposure-linkage.js +1 -9
  273. package/dist/sensor/readout-exposure-linkage.js.map +1 -1
  274. package/dist/sensor/readout-timing.js +4 -79
  275. package/dist/sensor/readout-timing.js.map +1 -1
  276. package/dist/sensor/response-application-compatibility.d.ts +2 -0
  277. package/dist/sensor/response-application-compatibility.js +4 -35
  278. package/dist/sensor/response-application-compatibility.js.map +1 -1
  279. package/dist/sensor/response-operating-range.d.ts +1 -0
  280. package/dist/sensor/response-operating-range.js +3 -79
  281. package/dist/sensor/response-operating-range.js.map +1 -1
  282. package/dist/sensor/responsivity-photocurrent.js +4 -114
  283. package/dist/sensor/responsivity-photocurrent.js.map +1 -1
  284. package/dist/sensor/sampling-aperture.js +1 -25
  285. package/dist/sensor/sampling-aperture.js.map +1 -1
  286. package/dist/sensor/sensor-characteristics.d.ts +137 -0
  287. package/dist/sensor/sensor-characteristics.js +115 -0
  288. package/dist/sensor/sensor-characteristics.js.map +1 -0
  289. package/dist/sensor/spatial-sample-reduction.js +3 -24
  290. package/dist/sensor/spatial-sample-reduction.js.map +1 -1
  291. package/dist/sensor/spatial-sampling-quadrature.js +1 -3
  292. package/dist/sensor/spatial-sampling-quadrature.js.map +1 -1
  293. package/dist/sensor/spatio-spectral-reduction.js +1 -18
  294. package/dist/sensor/spatio-spectral-reduction.js.map +1 -1
  295. package/dist/sensor/spectral-coverage.d.ts +10 -1
  296. package/dist/sensor/spectral-coverage.js +1 -1
  297. package/dist/sensor/spectral-coverage.js.map +1 -1
  298. package/dist/sensor/spectral-quadrature.js +3 -41
  299. package/dist/sensor/spectral-quadrature.js.map +1 -1
  300. package/dist/sensor/spectral-response.js +1 -47
  301. package/dist/sensor/spectral-response.js.map +1 -1
  302. package/dist/sensor/temporal-photo-signal.d.ts +3 -0
  303. package/dist/sensor/temporal-photo-signal.js +5 -2
  304. package/dist/sensor/temporal-photo-signal.js.map +1 -1
  305. package/dist/stabilization/camera-shake.js +1 -6
  306. package/dist/stabilization/camera-shake.js.map +1 -1
  307. package/dist/stabilization/system.d.ts +9 -0
  308. package/dist/stabilization/system.js +7 -86
  309. package/dist/stabilization/system.js.map +1 -1
  310. package/docs/AGENT_GUIDE.md +5 -0
  311. package/docs/API_REFERENCE.md +116 -3
  312. package/docs/QUICK_START.md +178 -14
  313. package/docs/USAGE.md +111 -3
  314. package/docs/api/capture-native-raw-dng.md +6 -0
  315. package/docs/api/core-version.md +1 -1
  316. package/docs/api/equipment-generic-lens-catalogue.md +7 -2
  317. package/docs/api/exports.json +203 -3
  318. package/docs/api/exposure-filtered-exposure-time.md +105 -0
  319. package/docs/api/facade-develop-joined-parts.md +32 -0
  320. package/docs/api/facade-display-view-gpu.md +5 -2
  321. package/docs/api/facade-fast-methods.md +91 -0
  322. package/docs/api/facade-simulate-capture.md +72 -16
  323. package/docs/api/facade-simulate-display-view.md +3 -2
  324. package/docs/api/optics-aperture-diameter.md +51 -0
  325. package/docs/api/optics-detail-limit.md +203 -0
  326. package/docs/api/optics-generic-nd-filter-presets.md +34 -0
  327. package/docs/api/optics-lens-psf-profile.md +3 -1
  328. package/docs/api/output-crop-to-match-focal-length.md +67 -0
  329. package/docs/api/output-developed-lens-corrections.md +12 -0
  330. package/docs/api/output-generic-lens-corrections.md +3 -10
  331. package/docs/api/output-lens-corrections.md +11 -1
  332. package/docs/api/output-print-size-blur-noise.md +115 -0
  333. package/docs/api/sensor-sensor-characteristics.md +105 -0
  334. package/llms.txt +5 -0
  335. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"program-line.js","sourceRoot":"","sources":["../../src/exposure/program-line.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Generic exposure program lines, for teaching and for products. A program line is the curve of\n * aperture/shutter pairs a camera's Program mode follows.\n *\n * A program line is control policy, not physics. Each node declares a wanted aperture/shutter pair at\n * an explicit number of stops of optical exposure, relative to the resolver's reference exposure.\n * The resolver later checks that every node is physically consistent with that reference and with\n * what the equipment can do.\n * @see docs/USAGE.md for the equations, units, coordinate conventions, known blockers and support\n * limits.\n */\n\nimport { rejectUnknownFields } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport const EXPOSURE_PROGRAM_LINE_SCHEMA_VERSION =\n \"0.1.0\" as const;\n\nexport interface ExposureProgramLineNode {\n nodeId: string;\n opticalExposureStopsFromReference: number;\n aperture: number;\n shutterSeconds: number;\n}\n\nexport interface ExposureProgramLineProfile {\n schemaVersion:\n typeof EXPOSURE_PROGRAM_LINE_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n scientificStatus: \"approximation\";\n policyKind:\n \"generic-program-line\";\n interpolation:\n \"log2-aperture-shutter\";\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n nodes:\n readonly ExposureProgramLineNode[];\n}\n\nfunction requireRecord(\n value: unknown,\n path: string,\n allowedKeys: readonly string[] | null\n): UnknownRecord {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be an object.\"\n );\n }\n if (allowedKeys !== null) rejectUnknownFields(value, allowedKeys, path);\n return value as UnknownRecord;\n}\n\nfunction requireNonEmptyString(\n value: unknown,\n path: string\n): string {\n if (\n typeof value !== \"string\" ||\n value.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n path + \" must be a non-empty string.\"\n );\n }\n return value.trim();\n}\n\nfunction requireFinite(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be finite.\"\n );\n }\n return value;\n}\n\nfunction requirePositiveFinite(\n value: unknown,\n path: string\n): number {\n const parsed =\n requireFinite(value, path);\n if (parsed <= 0) {\n throw new InvalidConfigurationError(\n path +\n \" must be greater than zero.\"\n );\n }\n return parsed;\n}\n\nfunction parseLimitations(\n value: unknown,\n path: string\n): readonly string[] {\n if (!Array.isArray(value)) {\n throw new InvalidConfigurationError(\n path + \" must be an array.\"\n );\n }\n const parsed = value.map(\n (entry, index) =>\n requireNonEmptyString(\n entry,\n path + \"[\" + index + \"]\"\n )\n );\n if (\n new Set(parsed).size !==\n parsed.length\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must not contain duplicates.\"\n );\n }\n return parsed;\n}\n\n/**\n * Parses a generic educational/product exposure program line.\n *\n * A program line is control policy, not physics. Each node declares a wanted\n * aperture/shutter pair at an explicit number of stops of optical exposure,\n * relative to the resolver's reference exposure. The resolver later checks\n * that every node is physically consistent with that reference and with what\n * the equipment can do.\n */\nexport function parseExposureProgramLineProfile(\n value: unknown\n): ExposureProgramLineProfile {\n const record = requireRecord(\n value,\n \"exposureProgramLineProfile\", [\"schemaVersion\", \"scientificStatus\", \"policyKind\", \"interpolation\", \"nodes\", \"profileId\", \"profileVersion\", \"evidence\", \"limitations\"]\n );\n\n if (\n record.schemaVersion !==\n EXPOSURE_PROGRAM_LINE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'exposureProgramLineProfile.schemaVersion must be \"' +\n EXPOSURE_PROGRAM_LINE_SCHEMA_VERSION +\n '\".'\n );\n }\n if (\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n 'exposureProgramLineProfile.scientificStatus must be \"approximation\".'\n );\n }\n if (\n record.policyKind !==\n \"generic-program-line\"\n ) {\n throw new InvalidConfigurationError(\n 'exposureProgramLineProfile.policyKind must be \"generic-program-line\".'\n );\n }\n if (\n record.interpolation !==\n \"log2-aperture-shutter\"\n ) {\n throw new InvalidConfigurationError(\n 'exposureProgramLineProfile.interpolation must be \"log2-aperture-shutter\".'\n );\n }\n if (\n !Array.isArray(record.nodes) ||\n record.nodes.length < 2\n ) {\n throw new InvalidConfigurationError(\n \"exposureProgramLineProfile.nodes must contain at least two nodes.\"\n );\n }\n\n let previousStops =\n Number.NEGATIVE_INFINITY;\n const ids: string[] = [];\n\n const nodes = record.nodes.map(\n (entry, index) => {\n const path =\n \"exposureProgramLineProfile.nodes[\" +\n index +\n \"]\";\n const node =\n requireRecord(entry, path, [\"nodeId\", \"opticalExposureStopsFromReference\", \"aperture\", \"shutterSeconds\"]);\n const nodeId =\n requireNonEmptyString(\n node.nodeId,\n path + \".nodeId\"\n );\n const stops =\n requireFinite(\n node\n .opticalExposureStopsFromReference,\n path +\n \".opticalExposureStopsFromReference\"\n );\n if (stops <= previousStops) {\n throw new InvalidConfigurationError(\n \"exposureProgramLineProfile.nodes opticalExposureStopsFromReference must be strictly increasing.\"\n );\n }\n previousStops = stops;\n ids.push(nodeId);\n\n return {\n nodeId,\n opticalExposureStopsFromReference:\n stops,\n aperture:\n requirePositiveFinite(\n node.aperture,\n path + \".aperture\"\n ),\n shutterSeconds:\n requirePositiveFinite(\n node.shutterSeconds,\n path +\n \".shutterSeconds\"\n )\n };\n }\n );\n\n if (\n new Set(ids).size !== ids.length\n ) {\n throw new InvalidConfigurationError(\n \"exposureProgramLineProfile.nodes[].nodeId must not contain duplicates.\"\n );\n }\n\n return {\n schemaVersion:\n EXPOSURE_PROGRAM_LINE_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"exposureProgramLineProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"exposureProgramLineProfile.profileVersion\"\n ),\n scientificStatus:\n \"approximation\",\n policyKind:\n \"generic-program-line\",\n interpolation:\n \"log2-aperture-shutter\",\n evidence: parseEvidenceList(\n record.evidence,\n \"exposureProgramLineProfile.evidence\"\n ),\n limitations:\n parseLimitations(\n record.limitations,\n \"exposureProgramLineProfile.limitations\"\n ),\n nodes\n };\n}\n"]}
1
+ {"version":3,"file":"program-line.js","sourceRoot":"","sources":["../../src/exposure/program-line.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Generic exposure program lines, for teaching and for products. A program line is the curve of\n * aperture/shutter pairs a camera's Program mode follows.\n *\n * A program line is control policy, not physics. Each node declares a wanted aperture/shutter pair at\n * an explicit number of stops of optical exposure, relative to the resolver's reference exposure.\n * The resolver later checks that every node is physically consistent with that reference and with\n * what the equipment can do.\n * @see docs/USAGE.md for the equations, units, coordinate conventions, known blockers and support\n * limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport { requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, requireConfigFinite as requireFinite, parseConfigLimitations as parseLimitations, requireConfigFiniteAboveZero as requirePositiveFinite } from \"../core/record-validation.js\";\n\nexport const EXPOSURE_PROGRAM_LINE_SCHEMA_VERSION =\n \"0.1.0\" as const;\n\nexport interface ExposureProgramLineNode {\n nodeId: string;\n opticalExposureStopsFromReference: number;\n aperture: number;\n shutterSeconds: number;\n}\n\nexport interface ExposureProgramLineProfile {\n schemaVersion:\n typeof EXPOSURE_PROGRAM_LINE_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n scientificStatus: \"approximation\";\n policyKind:\n \"generic-program-line\";\n interpolation:\n \"log2-aperture-shutter\";\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n nodes:\n readonly ExposureProgramLineNode[];\n}\n\n/**\n * Parses a generic educational/product exposure program line.\n *\n * A program line is control policy, not physics. Each node declares a wanted\n * aperture/shutter pair at an explicit number of stops of optical exposure,\n * relative to the resolver's reference exposure. The resolver later checks\n * that every node is physically consistent with that reference and with what\n * the equipment can do.\n */\nexport function parseExposureProgramLineProfile(\n value: unknown\n): ExposureProgramLineProfile {\n const record = requireRecord(\n value,\n \"exposureProgramLineProfile\", [\"schemaVersion\", \"scientificStatus\", \"policyKind\", \"interpolation\", \"nodes\", \"profileId\", \"profileVersion\", \"evidence\", \"limitations\"]\n );\n\n if (\n record.schemaVersion !==\n EXPOSURE_PROGRAM_LINE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'exposureProgramLineProfile.schemaVersion must be \"' +\n EXPOSURE_PROGRAM_LINE_SCHEMA_VERSION +\n '\".'\n );\n }\n if (\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n 'exposureProgramLineProfile.scientificStatus must be \"approximation\".'\n );\n }\n if (\n record.policyKind !==\n \"generic-program-line\"\n ) {\n throw new InvalidConfigurationError(\n 'exposureProgramLineProfile.policyKind must be \"generic-program-line\".'\n );\n }\n if (\n record.interpolation !==\n \"log2-aperture-shutter\"\n ) {\n throw new InvalidConfigurationError(\n 'exposureProgramLineProfile.interpolation must be \"log2-aperture-shutter\".'\n );\n }\n if (\n !Array.isArray(record.nodes) ||\n record.nodes.length < 2\n ) {\n throw new InvalidConfigurationError(\n \"exposureProgramLineProfile.nodes must contain at least two nodes.\"\n );\n }\n\n let previousStops =\n Number.NEGATIVE_INFINITY;\n const ids: string[] = [];\n\n const nodes = record.nodes.map(\n (entry, index) => {\n const path =\n \"exposureProgramLineProfile.nodes[\" +\n index +\n \"]\";\n const node =\n requireRecord(entry, path, [\"nodeId\", \"opticalExposureStopsFromReference\", \"aperture\", \"shutterSeconds\"]);\n const nodeId =\n requireNonEmptyString(\n node.nodeId,\n path + \".nodeId\"\n );\n const stops =\n requireFinite(\n node\n .opticalExposureStopsFromReference,\n path +\n \".opticalExposureStopsFromReference\"\n );\n if (stops <= previousStops) {\n throw new InvalidConfigurationError(\n \"exposureProgramLineProfile.nodes opticalExposureStopsFromReference must be strictly increasing.\"\n );\n }\n previousStops = stops;\n ids.push(nodeId);\n\n return {\n nodeId,\n opticalExposureStopsFromReference:\n stops,\n aperture:\n requirePositiveFinite(\n node.aperture,\n path + \".aperture\"\n ),\n shutterSeconds:\n requirePositiveFinite(\n node.shutterSeconds,\n path +\n \".shutterSeconds\"\n )\n };\n }\n );\n\n if (\n new Set(ids).size !== ids.length\n ) {\n throw new InvalidConfigurationError(\n \"exposureProgramLineProfile.nodes[].nodeId must not contain duplicates.\"\n );\n }\n\n return {\n schemaVersion:\n EXPOSURE_PROGRAM_LINE_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"exposureProgramLineProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"exposureProgramLineProfile.profileVersion\"\n ),\n scientificStatus:\n \"approximation\",\n policyKind:\n \"generic-program-line\",\n interpolation:\n \"log2-aperture-shutter\",\n evidence: parseEvidenceList(\n record.evidence,\n \"exposureProgramLineProfile.evidence\"\n ),\n limitations:\n parseLimitations(\n record.limitations,\n \"exposureProgramLineProfile.limitations\"\n ),\n nodes\n };\n}\n"]}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Develop joined parts (#571): the whole-image development steps of a capture whose RAW was rendered in parts.
3
+ * @see docs/QUICK_START.md, "Developing a capture rendered in parts".
4
+ */
5
+ import { type SimulateCaptureDngPart, type SimulateCaptureOptions, type SimulateCaptureResult } from "./simulate-capture.js";
6
+ /**
7
+ * Develops the whole frame of `options` from the packed RAW of region renders of the same request (#571), so a capture can
8
+ * render its RAW in parallel parts and still take the development steps that filter across the whole image:
9
+ * `output.diffractionCorrection` and `output.sharpening`, which a region render refuses, and `output.lensCorrections` (#570), which
10
+ * runs on the whole developed frame here exactly as in `simulateCapture(options)`. The parts are joined exactly as
11
+ * {@link serializeSimulatedCaptureDngFromParts} joins them (they must cover every native site and agree where they overlap),
12
+ * and the joined RAW is the whole render's RAW, so the result's `image` (samples and JPEG or PNG bytes), `raw` codes and
13
+ * `plan` are those of `simulateCapture(options)`, bit for bit.
14
+ *
15
+ * `options` is the whole request (no `output.region`), with the development options it should have; render the parts with
16
+ * the same request plus `output.region`, without `output.diffractionCorrection`, `output.sharpening` and `output.dng`, and with a
17
+ * fixed white balance in place of `"auto"` (none of these change the RAW codes; auto white balance is measured here over the
18
+ * joined frame). A part may keep or drop `output.lensCorrections` (a corrected region only widens its `region.nativeRect`).
19
+ * Any `output.format` serves for a part.
20
+ *
21
+ * `onProgress` reports the `white-balance` (with auto white balance), `development`, `diffraction-correction`, `sharpening` and
22
+ * `jpeg` stages, the detail stages once per output row, so a host can show "Applying sharpening to the whole image". The lens
23
+ * corrections report no stage of their own: they run between `diffraction-correction` and `sharpening`.
24
+ * No `raw` stage is reported: no RAW is rendered. What differs from the whole render's result: `diagnostics.providerEvaluationCount`
25
+ * is 0, `diagnostics.timingsMs` are this call's, `diagnostics.fast` and the `raw.*` assumptions of how the RAW was rendered are
26
+ * not repeated (they are in the parts' results), and a `parts` assumption records the join.
27
+ * @returns The capture result of `options`, developed from the joined RAW.
28
+ */
29
+ export declare function simulateCaptureFromParts(options: SimulateCaptureOptions, parts: readonly SimulateCaptureDngPart[]): Promise<SimulateCaptureResult>;
@@ -0,0 +1,33 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ /**
3
+ * Develop joined parts (#571): the whole-image development steps of a capture whose RAW was rendered in parts.
4
+ * @see docs/QUICK_START.md, "Developing a capture rendered in parts".
5
+ */
6
+ import { runCapture } from "./simulate-capture.js";
7
+ /**
8
+ * Develops the whole frame of `options` from the packed RAW of region renders of the same request (#571), so a capture can
9
+ * render its RAW in parallel parts and still take the development steps that filter across the whole image:
10
+ * `output.diffractionCorrection` and `output.sharpening`, which a region render refuses, and `output.lensCorrections` (#570), which
11
+ * runs on the whole developed frame here exactly as in `simulateCapture(options)`. The parts are joined exactly as
12
+ * {@link serializeSimulatedCaptureDngFromParts} joins them (they must cover every native site and agree where they overlap),
13
+ * and the joined RAW is the whole render's RAW, so the result's `image` (samples and JPEG or PNG bytes), `raw` codes and
14
+ * `plan` are those of `simulateCapture(options)`, bit for bit.
15
+ *
16
+ * `options` is the whole request (no `output.region`), with the development options it should have; render the parts with
17
+ * the same request plus `output.region`, without `output.diffractionCorrection`, `output.sharpening` and `output.dng`, and with a
18
+ * fixed white balance in place of `"auto"` (none of these change the RAW codes; auto white balance is measured here over the
19
+ * joined frame). A part may keep or drop `output.lensCorrections` (a corrected region only widens its `region.nativeRect`).
20
+ * Any `output.format` serves for a part.
21
+ *
22
+ * `onProgress` reports the `white-balance` (with auto white balance), `development`, `diffraction-correction`, `sharpening` and
23
+ * `jpeg` stages, the detail stages once per output row, so a host can show "Applying sharpening to the whole image". The lens
24
+ * corrections report no stage of their own: they run between `diffraction-correction` and `sharpening`.
25
+ * No `raw` stage is reported: no RAW is rendered. What differs from the whole render's result: `diagnostics.providerEvaluationCount`
26
+ * is 0, `diagnostics.timingsMs` are this call's, `diagnostics.fast` and the `raw.*` assumptions of how the RAW was rendered are
27
+ * not repeated (they are in the parts' results), and a `parts` assumption records the join.
28
+ * @returns The capture result of `options`, developed from the joined RAW.
29
+ */
30
+ export async function simulateCaptureFromParts(options, parts) {
31
+ return await runCapture(options, "develop-from-parts", parts);
32
+ }
33
+ //# sourceMappingURL=develop-joined-parts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"develop-joined-parts.js","sourceRoot":"","sources":["../../src/facade/develop-joined-parts.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAwF,MAAM,uBAAuB,CAAC;AAEzI;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,OAA+B,EAAE,KAAwC;IACtH,OAAO,MAAM,UAAU,CAAC,OAAO,EAAE,oBAAoB,EAAE,KAAK,CAA0B,CAAC;AACzF,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Develop joined parts (#571): the whole-image development steps of a capture whose RAW was rendered in parts.\n * @see docs/QUICK_START.md, \"Developing a capture rendered in parts\".\n */\n\nimport { runCapture, type SimulateCaptureDngPart, type SimulateCaptureOptions, type SimulateCaptureResult } from \"./simulate-capture.js\";\n\n/**\n * Develops the whole frame of `options` from the packed RAW of region renders of the same request (#571), so a capture can\n * render its RAW in parallel parts and still take the development steps that filter across the whole image:\n * `output.diffractionCorrection` and `output.sharpening`, which a region render refuses, and `output.lensCorrections` (#570), which\n * runs on the whole developed frame here exactly as in `simulateCapture(options)`. The parts are joined exactly as\n * {@link serializeSimulatedCaptureDngFromParts} joins them (they must cover every native site and agree where they overlap),\n * and the joined RAW is the whole render's RAW, so the result's `image` (samples and JPEG or PNG bytes), `raw` codes and\n * `plan` are those of `simulateCapture(options)`, bit for bit.\n *\n * `options` is the whole request (no `output.region`), with the development options it should have; render the parts with\n * the same request plus `output.region`, without `output.diffractionCorrection`, `output.sharpening` and `output.dng`, and with a\n * fixed white balance in place of `\"auto\"` (none of these change the RAW codes; auto white balance is measured here over the\n * joined frame). A part may keep or drop `output.lensCorrections` (a corrected region only widens its `region.nativeRect`).\n * Any `output.format` serves for a part.\n *\n * `onProgress` reports the `white-balance` (with auto white balance), `development`, `diffraction-correction`, `sharpening` and\n * `jpeg` stages, the detail stages once per output row, so a host can show \"Applying sharpening to the whole image\". The lens\n * corrections report no stage of their own: they run between `diffraction-correction` and `sharpening`.\n * No `raw` stage is reported: no RAW is rendered. What differs from the whole render's result: `diagnostics.providerEvaluationCount`\n * is 0, `diagnostics.timingsMs` are this call's, `diagnostics.fast` and the `raw.*` assumptions of how the RAW was rendered are\n * not repeated (they are in the parts' results), and a `parts` assumption records the join.\n * @returns The capture result of `options`, developed from the joined RAW.\n */\nexport async function simulateCaptureFromParts(options: SimulateCaptureOptions, parts: readonly SimulateCaptureDngPart[]): Promise<SimulateCaptureResult> {\n return await runCapture(options, \"develop-from-parts\", parts) as SimulateCaptureResult;\n}\n"]}
@@ -10,13 +10,16 @@ import type { SimulateCaptureFastReport } from "./simulate-capture.js";
10
10
  export type DisplayViewGpuMode = "off" | "auto" | "require";
11
11
  /** 2.11 (#481): the second argument of `prepareDisplayView`. */
12
12
  export interface PrepareDisplayViewOptions {
13
- /** See {@link DisplayViewGpuMode}. Default `"off"`. */
13
+ /**
14
+ * See {@link DisplayViewGpuMode}. 2.20.0: default `"auto"` when the request resolves to fast (`fast` omitted or true: the
15
+ * display view's default) and `"off"` when it is exact (`fast: false`); an explicit value wins.
16
+ */
14
17
  gpu?: DisplayViewGpuMode;
15
18
  /**
16
19
  * Where the device comes from, with `gpu: "auto"` or `"require"`: a WebGPU entry point (a worker's `navigator.gpu`), or an
17
20
  * `ImageKernelAccelerator` whose device the view shares (the accelerator keeps ownership; `dispose()` of the prepared view
18
21
  * leaves it alone). Without it the engine acquires a device from `globalThis.navigator.gpu` and owns it until `dispose()`.
19
- * Refused with `gpu: "off"`.
22
+ * Refused when `gpu` is or defaults to `"off"`.
20
23
  */
21
24
  gpuDevice?: unknown;
22
25
  }
@@ -25,8 +28,8 @@ export interface ParsedPrepareDisplayViewOptions {
25
28
  gpu: DisplayViewGpuMode;
26
29
  gpuDevice: unknown;
27
30
  }
28
- /** Internal: validates the second argument of `prepareDisplayView`. */
29
- export declare function parsePrepareDisplayViewOptions(value: unknown): ParsedPrepareDisplayViewOptions;
31
+ /** Internal: validates the second argument of `prepareDisplayView`; `fast` is the request's resolved top-level fast (the GPU default). */
32
+ export declare function parsePrepareDisplayViewOptions(value: unknown, fast?: boolean): ParsedPrepareDisplayViewOptions;
30
33
  /**
31
34
  * 2.11 (#481): why a display view that asked for the GPU (`gpu: "auto"`) ran the CPU reference. The accelerator's acquisition
32
35
  * reasons, plus: `unsupported-on-backend` (no GPU display-view renderer exists in this version, or it does not support the
@@ -14,17 +14,17 @@
14
14
  * `"auto"` runs the CPU reference labelled `unsupported-on-backend` without touching a device, and `"require"` fails with that reason.
15
15
  */
16
16
  import { InvalidConfigurationError } from "../core/configuration-error.js";
17
- /** Internal: validates the second argument of `prepareDisplayView`. */
18
- export function parsePrepareDisplayViewOptions(value) {
17
+ /** Internal: validates the second argument of `prepareDisplayView`; `fast` is the request's resolved top-level fast (the GPU default). */
18
+ export function parsePrepareDisplayViewOptions(value, fast = false) {
19
19
  if (value === undefined)
20
- return { gpu: "off", gpuDevice: undefined };
20
+ value = {};
21
21
  if (typeof value !== "object" || value === null || Array.isArray(value))
22
22
  throw new InvalidConfigurationError("prepareDisplayView options must be an object { gpu, gpuDevice }.");
23
23
  for (const key of Object.keys(value))
24
24
  if (key !== "gpu" && key !== "gpuDevice")
25
25
  throw new InvalidConfigurationError("Unknown prepareDisplayView options field: " + key + ".");
26
26
  const { gpu, gpuDevice } = value;
27
- const mode = gpu === undefined ? "off" : gpu;
27
+ const mode = gpu === undefined ? fast ? "auto" : "off" : gpu;
28
28
  if (mode !== "off" && mode !== "auto" && mode !== "require")
29
29
  throw new InvalidConfigurationError("prepareDisplayView options.gpu must be \"off\", \"auto\" or \"require\".");
30
30
  if (gpuDevice !== undefined && (typeof gpuDevice !== "object" || gpuDevice === null))
@@ -1 +1 @@
1
- {"version":3,"file":"display-view-gpu.js","sourceRoot":"","sources":["../../src/facade/display-view-gpu.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * #481: how a prepared display view chooses between a WebGPU preview renderer and the CPU reference, and how a render labels\n * which ran. This module holds the option, the label and the renderer contract and imports nothing from the GPU code, so a\n * bundle that never asks for the GPU (`gpu: \"off\"`, the default) does not contain it; the device handling lives in\n * `display-view-gpu-session.ts`, loaded on demand by `prepareDisplayView` when `gpu` is `\"auto\"` or `\"require\"`.\n *\n * The vocabulary is the image-kernel accelerator's (`createImageKernelAccelerator`, docs/WEBGPU.md): `\"auto\"` is\n * `backend: \"webgpu-f32\"` with `fallback: \"cpu-reference\"`, `\"require\"` is `fallback: \"fail\"`, `\"off\"` is\n * `backend: \"cpu-reference\"`. The render's `diagnostics.fast.execution` names the backend that ran, the fallback reason and the\n * bound in the fields of `ImageKernelExecution`, plus the adapter and the run-time conformance check.\n *\n * No GPU display-view renderer exists yet (#478, #479): until one registers itself through {@link setDisplayViewGpuRendererFactory},\n * `\"auto\"` runs the CPU reference labelled `unsupported-on-backend` without touching a device, and `\"require\"` fails with that reason.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport type { ChartCompositeProbeRecord, ImageKernelAdapterDescription, ImageKernelBackend, ImageKernelExecution, ImageKernelFallbackReason } from \"../gpu/image-kernel-execution.js\";\nimport type { DisplayViewRenderResult, DisplayViewSetup } from \"./display-view.js\";\nimport type { SimulateCaptureFastReport } from \"./simulate-capture.js\";\n\n/**\n * 2.11 (#481): whether a prepared display view may render on the GPU. `\"off\"` (the default) is the CPU reference, today's\n * behaviour byte for byte. `\"auto\"` renders on WebGPU when a conforming device is available and the request is supported, and\n * otherwise runs the CPU reference and says why. `\"require\"` fails instead of falling back. In the accelerator's words: `\"auto\"`\n * is `backend: \"webgpu-f32\"` with `fallback: \"cpu-reference\"`, `\"require\"` is `fallback: \"fail\"`, `\"off\"` is `backend: \"cpu-reference\"`.\n */\nexport type DisplayViewGpuMode = \"off\" | \"auto\" | \"require\";\n\n/** 2.11 (#481): the second argument of `prepareDisplayView`. */\nexport interface PrepareDisplayViewOptions {\n /** See {@link DisplayViewGpuMode}. Default `\"off\"`. */\n gpu?: DisplayViewGpuMode;\n /**\n * Where the device comes from, with `gpu: \"auto\"` or `\"require\"`: a WebGPU entry point (a worker's `navigator.gpu`), or an\n * `ImageKernelAccelerator` whose device the view shares (the accelerator keeps ownership; `dispose()` of the prepared view\n * leaves it alone). Without it the engine acquires a device from `globalThis.navigator.gpu` and owns it until `dispose()`.\n * Refused with `gpu: \"off\"`.\n */\n gpuDevice?: unknown;\n}\n\n/** The parsed form of {@link PrepareDisplayViewOptions}. @internal */\nexport interface ParsedPrepareDisplayViewOptions { gpu: DisplayViewGpuMode; gpuDevice: unknown }\n\n/** Internal: validates the second argument of `prepareDisplayView`. */\nexport function parsePrepareDisplayViewOptions(value: unknown): ParsedPrepareDisplayViewOptions {\n if (value === undefined) return { gpu: \"off\", gpuDevice: undefined };\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) throw new InvalidConfigurationError(\"prepareDisplayView options must be an object { gpu, gpuDevice }.\");\n for (const key of Object.keys(value)) if (key !== \"gpu\" && key !== \"gpuDevice\") throw new InvalidConfigurationError(\"Unknown prepareDisplayView options field: \" + key + \".\");\n const { gpu, gpuDevice } = value as Record<string, unknown>;\n const mode: DisplayViewGpuMode = gpu === undefined ? \"off\" : gpu as DisplayViewGpuMode;\n if (mode !== \"off\" && mode !== \"auto\" && mode !== \"require\") throw new InvalidConfigurationError(\"prepareDisplayView options.gpu must be \\\"off\\\", \\\"auto\\\" or \\\"require\\\".\");\n if (gpuDevice !== undefined && (typeof gpuDevice !== \"object\" || gpuDevice === null)) throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice must be a WebGPU entry point (navigator.gpu) or an ImageKernelAccelerator.\");\n if (gpuDevice !== undefined && mode === \"off\") throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice needs gpu \\\"auto\\\" or \\\"require\\\".\");\n return { gpu: mode, gpuDevice };\n}\n\n/**\n * 2.11 (#481): why a display view that asked for the GPU (`gpu: \"auto\"`) ran the CPU reference. The accelerator's acquisition\n * reasons, plus: `unsupported-on-backend` (no GPU display-view renderer exists in this version, or it does not support the\n * request), `conformance-failed` (the device failed the run-time self-check before the view's first GPU render), `device-lost`\n * (the device was lost; the rest of the view runs on the CPU) and `disposed` (the prepared view was disposed).\n */\nexport type DisplayViewGpuFallbackReason = ImageKernelFallbackReason | \"unsupported-on-backend\" | \"conformance-failed\" | \"device-lost\" | \"disposed\";\n\n/** 2.11 (#481): the run-time conformance self-check of a device, run once before the view's first GPU render. */\nexport interface DisplayViewGpuConformance {\n /** The ids of the cases run, in order (the built-in image-kernel cases, then the renderer's own). */\n cases: readonly string[];\n passed: boolean;\n /** The first case that failed, or null. */\n failedCase: string | null;\n /** What the failed case reported, or null. */\n detail: string | null;\n}\n\n/**\n * 2.11 (#481): where a display view's render ran, in the words of the image-kernel execution record (`ImageKernelExecution`):\n * `backend` names the path that ran (`cpu-reference`, the float64 engine reference, or `webgpu-f32`, a float32 approximation\n * within `errorBound`), `requestedBackend` what `gpu` asked for, and `fallbackReason` why a request for the GPU ran the CPU.\n * `adapter` describes the device's adapter whenever one was involved, also when the view then fell back; `conformance` is\n * the device's self-check once it has run. A CPU render keeps `assurance: \"engine-reference\"` and `fast: false`.\n */\nexport interface DisplayViewExecution extends Omit<ImageKernelExecution, \"fallbackReason\"> {\n /** The `gpu` option the view was prepared with. */\n gpu: DisplayViewGpuMode;\n fallbackReason: DisplayViewGpuFallbackReason | null;\n adapter: ImageKernelAdapterDescription | null;\n conformance: DisplayViewGpuConformance | null;\n /**\n * 2.11: the composite chart kernel's device probe when this render needed it (composite charts, the 2.3 elements and\n * `material-layers` scenes): the device class and the product path the kernel ran with, or, on a refusal (`fallbackReason`\n * `unsupported-on-backend`), why. Null when the render did not run the probe (the 2.0 presets, `gpu: \"off\"`).\n */\n compositeProbe: ChartCompositeProbeRecord | null;\n}\n\n/** 2.11 (#481): `diagnostics.fast` of a display view: the capture's report plus where the render ran. */\nexport interface DisplayViewFastReport extends SimulateCaptureFastReport {\n /** Where this render ran (see {@link DisplayViewExecution}). `assurance` above follows it. */\n execution: DisplayViewExecution;\n}\n\nconst CPU_LIMITATIONS = /* @__PURE__ */ Object.freeze([\"Float64 engine reference execution; results are the reference by definition\"]);\n\n/** Internal: the execution record of a display view rendered on the CPU reference. `requested` names what `gpu` asked for. */\nexport function cpuDisplayViewExecution(gpu: DisplayViewGpuMode, fallbackReason: DisplayViewGpuFallbackReason | null, adapter: ImageKernelAdapterDescription | null,\n conformance: DisplayViewGpuConformance | null, detail?: string, compositeProbe: ChartCompositeProbeRecord | null = null): DisplayViewExecution {\n const requestedBackend: ImageKernelBackend = gpu === \"off\" ? \"cpu-reference\" : \"webgpu-f32\";\n const limitations = detail === undefined ? CPU_LIMITATIONS : Object.freeze([...CPU_LIMITATIONS, \"WebGPU was requested (gpu: \\\"\" + gpu + \"\\\") and the CPU reference ran: \" + detail]);\n return Object.freeze({ gpu, backend: \"cpu-reference\", requestedBackend, fallbackReason, arithmetic: \"float64\", assurance: \"engine-reference\", fast: false,\n bitIdenticalToReference: true, errorBound: null, diagnosticsExact: true, diagnosticUncertaintySampleCount: 0, limitations, adapter, conformance, compositeProbe });\n}\n\n// ---------------------------------------------------------------------------------------------------------------\n// The renderer contract (#478 implements it; until then the only implementation is a test fake).\n\n/**\n * Internal (#481): the device a renderer or conformance case runs on. It is the engine's `WebGpuRuntime` object\n * (`src/gpu/webgpu-runtime.ts`: `device`, `guard`, `destroy` and the rest), seen here through its WebGPU-free members only so\n * that no WebGPU type reaches the published declarations (docs/WEBGPU.md); a renderer in the engine casts it to `WebGpuRuntime`.\n */\nexport interface DisplayViewGpuRuntimeHandle {\n readonly adapter: ImageKernelAdapterDescription | null;\n readonly maximumStorageBindingBytes: number;\n readonly maximumWorkgroupsPerDimension: number;\n isLost(): boolean;\n}\n\n/** What a prepared request asks of a GPU renderer (`supports`): the options that shape a render. */\nexport interface DisplayViewGpuRequest {\n ahd: boolean;\n diffraction: boolean;\n antiAliasing: boolean;\n /** Pixel-aperture samples per axis (1: centre sampling). */\n boxSamples: number;\n toneCurve: \"identity\" | \"positive-reinhard-per-channel\";\n /**\n * #492: true when `lens.defocus` needs the defocus disc (out of focus): the expected signal then carries the disc, or each\n * node's diffraction kernel convolved with it, as site kernels (#492 step 2b), which the engine's renderer gathers in its\n * Quality site pass (step 2c). Absent or false otherwise.\n */\n defocus?: boolean;\n /**\n * #564: true when the defocus kernel's radius is above 64 sites, so the expected signal convolves it by runs on the CPU\n * (`largeKernel`); no GPU renderer takes it. Absent or false otherwise.\n */\n largeDefocus?: boolean;\n /**\n * #563: true when the request has `lens.projection`, `lens.distortion`, `lens.vignetting` or camera rotation: the CPU reference\n * renders it (display-view-lens-signal.ts) and no GPU renderer is asked or device requested (`unsupported-on-backend`).\n */\n lens?: boolean;\n /** The scene's form: an engine chart, a declared `material-layers` scene (#491), or a caller function. */\n scene: \"chart\" | \"material-layers\" | \"material-function\" | \"reflectance-function\" | \"radiance-function\";\n}\n/** One render of a region: the CPU renderer's own setup (tables, readout, demosaic, region, callbacks) and the render's signal. */\nexport interface DisplayViewGpuPart { setup: DisplayViewSetup; signal: AbortSignal | undefined }\n/** What a GPU render returns: the CPU renderer's result shape plus the a-priori bound of its values against the reference. */\nexport interface DisplayViewGpuRenderOutput extends DisplayViewRenderResult {\n errorBound: NonNullable<ImageKernelExecution[\"errorBound\"]>;\n /** Samples whose float32 classification fell inside its bound (0 when none). */\n diagnosticUncertaintySampleCount?: number;\n /** The composite chart kernel's device probe record, when the render used the composite material module. */\n compositeProbe?: ChartCompositeProbeRecord;\n}\n/** A conformance case: returns `true` when the device agrees with the reference within the case's bound, or a sentence saying how it did not. */\nexport interface DisplayViewGpuConformanceCase { id: string; run(runtime: DisplayViewGpuRuntimeHandle, signal: AbortSignal | undefined): Promise<true | string> }\n/**\n * Internal (#481): the contract a GPU display-view renderer fulfils (#478). One instance serves one device, created by the\n * registered factory for each prepared view that acquires or shares a device. `supports` says whether the renderer covers a\n * prepared request (`true`) or why not (a sentence; the view then runs the CPU reference labelled `unsupported-on-backend`).\n * `render` renders one region on the device and must throw `ImageKernelExecutionError` with reason `device-lost` or `aborted`\n * for those two events, as the accelerator's operations do; a render that throws `unsupported-on-backend` (a request the\n * renderer finds it does not cover only when rendering) runs the CPU reference labelled with that reason, or fails with it under\n * `\"require\"`. `conformanceCases` are run after the built-in image-kernel cases before the device's first render; a failure keeps\n * the whole view on the CPU. `dispose` releases what the renderer holds on the device (#491: uploaded scene records); the session\n * calls it when the prepared view is disposed.\n */\nexport interface DisplayViewGpuRenderer {\n readonly id: string;\n supports(request: DisplayViewGpuRequest): true | string;\n render(part: DisplayViewGpuPart): Promise<DisplayViewGpuRenderOutput>;\n readonly conformanceCases?: readonly DisplayViewGpuConformanceCase[];\n dispose?(): void;\n}\nexport type DisplayViewGpuRendererFactory = (runtime: DisplayViewGpuRuntimeHandle) => DisplayViewGpuRenderer;\n\nlet rendererFactory: DisplayViewGpuRendererFactory | null = null;\n/**\n * Internal (#481): registers the renderer that `prepareDisplayView` uses for `gpu: \"auto\" | \"require\"`, and returns the one\n * registered before (null: none). #478's renderer registers itself here; tests register a fake. With none registered no device\n * is requested and every GPU request falls back (or fails) with `unsupported-on-backend`.\n */\nexport function setDisplayViewGpuRendererFactory(factory: DisplayViewGpuRendererFactory | null): DisplayViewGpuRendererFactory | null {\n if (factory !== null && typeof factory !== \"function\") throw new InvalidConfigurationError(\"setDisplayViewGpuRendererFactory expects a function or null.\");\n const previous = rendererFactory;\n rendererFactory = factory;\n return previous;\n}\n/** Internal: the registered factory. */\nexport function displayViewGpuRendererFactory(): DisplayViewGpuRendererFactory | null { return rendererFactory; }\n"]}
1
+ {"version":3,"file":"display-view-gpu.js","sourceRoot":"","sources":["../../src/facade/display-view-gpu.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * #481: how a prepared display view chooses between a WebGPU preview renderer and the CPU reference, and how a render labels\n * which ran. This module holds the option, the label and the renderer contract and imports nothing from the GPU code, so a\n * bundle that never asks for the GPU (`gpu: \"off\"`, the default) does not contain it; the device handling lives in\n * `display-view-gpu-session.ts`, loaded on demand by `prepareDisplayView` when `gpu` is `\"auto\"` or `\"require\"`.\n *\n * The vocabulary is the image-kernel accelerator's (`createImageKernelAccelerator`, docs/WEBGPU.md): `\"auto\"` is\n * `backend: \"webgpu-f32\"` with `fallback: \"cpu-reference\"`, `\"require\"` is `fallback: \"fail\"`, `\"off\"` is\n * `backend: \"cpu-reference\"`. The render's `diagnostics.fast.execution` names the backend that ran, the fallback reason and the\n * bound in the fields of `ImageKernelExecution`, plus the adapter and the run-time conformance check.\n *\n * No GPU display-view renderer exists yet (#478, #479): until one registers itself through {@link setDisplayViewGpuRendererFactory},\n * `\"auto\"` runs the CPU reference labelled `unsupported-on-backend` without touching a device, and `\"require\"` fails with that reason.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport type { ChartCompositeProbeRecord, ImageKernelAdapterDescription, ImageKernelBackend, ImageKernelExecution, ImageKernelFallbackReason } from \"../gpu/image-kernel-execution.js\";\nimport type { DisplayViewRenderResult, DisplayViewSetup } from \"./display-view.js\";\nimport type { SimulateCaptureFastReport } from \"./simulate-capture.js\";\n\n/**\n * 2.11 (#481): whether a prepared display view may render on the GPU. `\"off\"` (the default) is the CPU reference, today's\n * behaviour byte for byte. `\"auto\"` renders on WebGPU when a conforming device is available and the request is supported, and\n * otherwise runs the CPU reference and says why. `\"require\"` fails instead of falling back. In the accelerator's words: `\"auto\"`\n * is `backend: \"webgpu-f32\"` with `fallback: \"cpu-reference\"`, `\"require\"` is `fallback: \"fail\"`, `\"off\"` is `backend: \"cpu-reference\"`.\n */\nexport type DisplayViewGpuMode = \"off\" | \"auto\" | \"require\";\n\n/** 2.11 (#481): the second argument of `prepareDisplayView`. */\nexport interface PrepareDisplayViewOptions {\n /**\n * See {@link DisplayViewGpuMode}. 2.20.0: default `\"auto\"` when the request resolves to fast (`fast` omitted or true: the\n * display view's default) and `\"off\"` when it is exact (`fast: false`); an explicit value wins.\n */\n gpu?: DisplayViewGpuMode;\n /**\n * Where the device comes from, with `gpu: \"auto\"` or `\"require\"`: a WebGPU entry point (a worker's `navigator.gpu`), or an\n * `ImageKernelAccelerator` whose device the view shares (the accelerator keeps ownership; `dispose()` of the prepared view\n * leaves it alone). Without it the engine acquires a device from `globalThis.navigator.gpu` and owns it until `dispose()`.\n * Refused when `gpu` is or defaults to `\"off\"`.\n */\n gpuDevice?: unknown;\n}\n\n/** The parsed form of {@link PrepareDisplayViewOptions}. @internal */\nexport interface ParsedPrepareDisplayViewOptions { gpu: DisplayViewGpuMode; gpuDevice: unknown }\n\n/** Internal: validates the second argument of `prepareDisplayView`; `fast` is the request's resolved top-level fast (the GPU default). */\nexport function parsePrepareDisplayViewOptions(value: unknown, fast = false): ParsedPrepareDisplayViewOptions {\n if (value === undefined) value = {};\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) throw new InvalidConfigurationError(\"prepareDisplayView options must be an object { gpu, gpuDevice }.\");\n for (const key of Object.keys(value)) if (key !== \"gpu\" && key !== \"gpuDevice\") throw new InvalidConfigurationError(\"Unknown prepareDisplayView options field: \" + key + \".\");\n const { gpu, gpuDevice } = value as Record<string, unknown>;\n const mode: DisplayViewGpuMode = gpu === undefined ? fast ? \"auto\" : \"off\" : gpu as DisplayViewGpuMode;\n if (mode !== \"off\" && mode !== \"auto\" && mode !== \"require\") throw new InvalidConfigurationError(\"prepareDisplayView options.gpu must be \\\"off\\\", \\\"auto\\\" or \\\"require\\\".\");\n if (gpuDevice !== undefined && (typeof gpuDevice !== \"object\" || gpuDevice === null)) throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice must be a WebGPU entry point (navigator.gpu) or an ImageKernelAccelerator.\");\n if (gpuDevice !== undefined && mode === \"off\") throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice needs gpu \\\"auto\\\" or \\\"require\\\".\");\n return { gpu: mode, gpuDevice };\n}\n\n/**\n * 2.11 (#481): why a display view that asked for the GPU (`gpu: \"auto\"`) ran the CPU reference. The accelerator's acquisition\n * reasons, plus: `unsupported-on-backend` (no GPU display-view renderer exists in this version, or it does not support the\n * request), `conformance-failed` (the device failed the run-time self-check before the view's first GPU render), `device-lost`\n * (the device was lost; the rest of the view runs on the CPU) and `disposed` (the prepared view was disposed).\n */\nexport type DisplayViewGpuFallbackReason = ImageKernelFallbackReason | \"unsupported-on-backend\" | \"conformance-failed\" | \"device-lost\" | \"disposed\";\n\n/** 2.11 (#481): the run-time conformance self-check of a device, run once before the view's first GPU render. */\nexport interface DisplayViewGpuConformance {\n /** The ids of the cases run, in order (the built-in image-kernel cases, then the renderer's own). */\n cases: readonly string[];\n passed: boolean;\n /** The first case that failed, or null. */\n failedCase: string | null;\n /** What the failed case reported, or null. */\n detail: string | null;\n}\n\n/**\n * 2.11 (#481): where a display view's render ran, in the words of the image-kernel execution record (`ImageKernelExecution`):\n * `backend` names the path that ran (`cpu-reference`, the float64 engine reference, or `webgpu-f32`, a float32 approximation\n * within `errorBound`), `requestedBackend` what `gpu` asked for, and `fallbackReason` why a request for the GPU ran the CPU.\n * `adapter` describes the device's adapter whenever one was involved, also when the view then fell back; `conformance` is\n * the device's self-check once it has run. A CPU render keeps `assurance: \"engine-reference\"` and `fast: false`.\n */\nexport interface DisplayViewExecution extends Omit<ImageKernelExecution, \"fallbackReason\"> {\n /** The `gpu` option the view was prepared with. */\n gpu: DisplayViewGpuMode;\n fallbackReason: DisplayViewGpuFallbackReason | null;\n adapter: ImageKernelAdapterDescription | null;\n conformance: DisplayViewGpuConformance | null;\n /**\n * 2.11: the composite chart kernel's device probe when this render needed it (composite charts, the 2.3 elements and\n * `material-layers` scenes): the device class and the product path the kernel ran with, or, on a refusal (`fallbackReason`\n * `unsupported-on-backend`), why. Null when the render did not run the probe (the 2.0 presets, `gpu: \"off\"`).\n */\n compositeProbe: ChartCompositeProbeRecord | null;\n}\n\n/** 2.11 (#481): `diagnostics.fast` of a display view: the capture's report plus where the render ran. */\nexport interface DisplayViewFastReport extends SimulateCaptureFastReport {\n /** Where this render ran (see {@link DisplayViewExecution}). `assurance` above follows it. */\n execution: DisplayViewExecution;\n}\n\nconst CPU_LIMITATIONS = /* @__PURE__ */ Object.freeze([\"Float64 engine reference execution; results are the reference by definition\"]);\n\n/** Internal: the execution record of a display view rendered on the CPU reference. `requested` names what `gpu` asked for. */\nexport function cpuDisplayViewExecution(gpu: DisplayViewGpuMode, fallbackReason: DisplayViewGpuFallbackReason | null, adapter: ImageKernelAdapterDescription | null,\n conformance: DisplayViewGpuConformance | null, detail?: string, compositeProbe: ChartCompositeProbeRecord | null = null): DisplayViewExecution {\n const requestedBackend: ImageKernelBackend = gpu === \"off\" ? \"cpu-reference\" : \"webgpu-f32\";\n const limitations = detail === undefined ? CPU_LIMITATIONS : Object.freeze([...CPU_LIMITATIONS, \"WebGPU was requested (gpu: \\\"\" + gpu + \"\\\") and the CPU reference ran: \" + detail]);\n return Object.freeze({ gpu, backend: \"cpu-reference\", requestedBackend, fallbackReason, arithmetic: \"float64\", assurance: \"engine-reference\", fast: false,\n bitIdenticalToReference: true, errorBound: null, diagnosticsExact: true, diagnosticUncertaintySampleCount: 0, limitations, adapter, conformance, compositeProbe });\n}\n\n// ---------------------------------------------------------------------------------------------------------------\n// The renderer contract (#478 implements it; until then the only implementation is a test fake).\n\n/**\n * Internal (#481): the device a renderer or conformance case runs on. It is the engine's `WebGpuRuntime` object\n * (`src/gpu/webgpu-runtime.ts`: `device`, `guard`, `destroy` and the rest), seen here through its WebGPU-free members only so\n * that no WebGPU type reaches the published declarations (docs/WEBGPU.md); a renderer in the engine casts it to `WebGpuRuntime`.\n */\nexport interface DisplayViewGpuRuntimeHandle {\n readonly adapter: ImageKernelAdapterDescription | null;\n readonly maximumStorageBindingBytes: number;\n readonly maximumWorkgroupsPerDimension: number;\n isLost(): boolean;\n}\n\n/** What a prepared request asks of a GPU renderer (`supports`): the options that shape a render. */\nexport interface DisplayViewGpuRequest {\n ahd: boolean;\n diffraction: boolean;\n antiAliasing: boolean;\n /** Pixel-aperture samples per axis (1: centre sampling). */\n boxSamples: number;\n toneCurve: \"identity\" | \"positive-reinhard-per-channel\";\n /**\n * #492: true when `lens.defocus` needs the defocus disc (out of focus): the expected signal then carries the disc, or each\n * node's diffraction kernel convolved with it, as site kernels (#492 step 2b), which the engine's renderer gathers in its\n * Quality site pass (step 2c). Absent or false otherwise.\n */\n defocus?: boolean;\n /**\n * #564: true when the defocus kernel's radius is above 64 sites, so the expected signal convolves it by runs on the CPU\n * (`largeKernel`); no GPU renderer takes it. Absent or false otherwise.\n */\n largeDefocus?: boolean;\n /**\n * #563: true when the request has `lens.projection`, `lens.distortion`, `lens.vignetting` or camera rotation: the CPU reference\n * renders it (display-view-lens-signal.ts) and no GPU renderer is asked or device requested (`unsupported-on-backend`).\n */\n lens?: boolean;\n /** The scene's form: an engine chart, a declared `material-layers` scene (#491), or a caller function. */\n scene: \"chart\" | \"material-layers\" | \"material-function\" | \"reflectance-function\" | \"radiance-function\";\n}\n/** One render of a region: the CPU renderer's own setup (tables, readout, demosaic, region, callbacks) and the render's signal. */\nexport interface DisplayViewGpuPart { setup: DisplayViewSetup; signal: AbortSignal | undefined }\n/** What a GPU render returns: the CPU renderer's result shape plus the a-priori bound of its values against the reference. */\nexport interface DisplayViewGpuRenderOutput extends DisplayViewRenderResult {\n errorBound: NonNullable<ImageKernelExecution[\"errorBound\"]>;\n /** Samples whose float32 classification fell inside its bound (0 when none). */\n diagnosticUncertaintySampleCount?: number;\n /** The composite chart kernel's device probe record, when the render used the composite material module. */\n compositeProbe?: ChartCompositeProbeRecord;\n}\n/** A conformance case: returns `true` when the device agrees with the reference within the case's bound, or a sentence saying how it did not. */\nexport interface DisplayViewGpuConformanceCase { id: string; run(runtime: DisplayViewGpuRuntimeHandle, signal: AbortSignal | undefined): Promise<true | string> }\n/**\n * Internal (#481): the contract a GPU display-view renderer fulfils (#478). One instance serves one device, created by the\n * registered factory for each prepared view that acquires or shares a device. `supports` says whether the renderer covers a\n * prepared request (`true`) or why not (a sentence; the view then runs the CPU reference labelled `unsupported-on-backend`).\n * `render` renders one region on the device and must throw `ImageKernelExecutionError` with reason `device-lost` or `aborted`\n * for those two events, as the accelerator's operations do; a render that throws `unsupported-on-backend` (a request the\n * renderer finds it does not cover only when rendering) runs the CPU reference labelled with that reason, or fails with it under\n * `\"require\"`. `conformanceCases` are run after the built-in image-kernel cases before the device's first render; a failure keeps\n * the whole view on the CPU. `dispose` releases what the renderer holds on the device (#491: uploaded scene records); the session\n * calls it when the prepared view is disposed.\n */\nexport interface DisplayViewGpuRenderer {\n readonly id: string;\n supports(request: DisplayViewGpuRequest): true | string;\n render(part: DisplayViewGpuPart): Promise<DisplayViewGpuRenderOutput>;\n readonly conformanceCases?: readonly DisplayViewGpuConformanceCase[];\n dispose?(): void;\n}\nexport type DisplayViewGpuRendererFactory = (runtime: DisplayViewGpuRuntimeHandle) => DisplayViewGpuRenderer;\n\nlet rendererFactory: DisplayViewGpuRendererFactory | null = null;\n/**\n * Internal (#481): registers the renderer that `prepareDisplayView` uses for `gpu: \"auto\" | \"require\"`, and returns the one\n * registered before (null: none). #478's renderer registers itself here; tests register a fake. With none registered no device\n * is requested and every GPU request falls back (or fails) with `unsupported-on-backend`.\n */\nexport function setDisplayViewGpuRendererFactory(factory: DisplayViewGpuRendererFactory | null): DisplayViewGpuRendererFactory | null {\n if (factory !== null && typeof factory !== \"function\") throw new InvalidConfigurationError(\"setDisplayViewGpuRendererFactory expects a function or null.\");\n const previous = rendererFactory;\n rendererFactory = factory;\n return previous;\n}\n/** Internal: the registered factory. */\nexport function displayViewGpuRendererFactory(): DisplayViewGpuRendererFactory | null { return rendererFactory; }\n"]}
@@ -20,7 +20,7 @@ export interface DisplayViewLensPsf {
20
20
  * #569: the field-dependent PSF of a display view from the sampled PSF the capture resolves (everything but the field point and wavelength),
21
21
  * of kernel radius R, on the W × H native raster of `pitch` µm.
22
22
  */
23
- export declare function createDisplayViewLensPsf(psf: Omit<ResolveLensSampledPsfInput, "fieldPointMm" | "wavelengthNm">, R: number, W: number, H: number, pitch: number): DisplayViewLensPsf;
23
+ export declare function createDisplayViewLensPsf(psf: Omit<ResolveLensSampledPsfInput, "fieldPointMm" | "wavelengthNm">, R: number, W: number, H: number, pitch: number, zones?: number): DisplayViewLensPsf;
24
24
  /** What the lens signal needs from the resolved request. */
25
25
  export interface DisplayViewLensSetup {
26
26
  geometry: PreparedDefocusImageSpaceGeometry;
@@ -33,7 +33,9 @@
33
33
  * across half a zone). A profile kernel's rows run with image +Y (up) and its tap (i, j) reads (x − (i − c)·p, y + (j − c)·p) in
34
34
  * native coordinates (`sensorPsfSourcePoint`), so the view's kernel (reading in(x − t)) is the profile kernel flipped vertically.
35
35
  * Each zone's combined kernels are the expected signal's own tables (`buildTables`) with the zone's kernels, built when a site of
36
- * the zone is first read and kept per input in a least-recently-used cache of at most 64 MB (at least four zones).
36
+ * the zone is first read and kept per input in a least-recently-used cache of at most 64 MB (at least four zones). The zones are the
37
+ * view's fast method for `lens.catalogue` (2.20.0); its exact method (`fast: false`) passes `zones` = max(W, H), one site per zone,
38
+ * the capture's own PSF at each site centre (much slower).
37
39
  *
38
40
  * Large defocus kernels (#564, `input.largeKernel`, radius above 64 sites). The image-space disc D is the same at every lattice
39
41
  * group, spectral node and temporal midpoint, so it commutes with those sums as in the rectilinear signal (`expected-signal.ts`):
@@ -52,8 +54,8 @@ export const DISPLAY_VIEW_LENS_PSF_ZONES = 64;
52
54
  * #569: the field-dependent PSF of a display view from the sampled PSF the capture resolves (everything but the field point and wavelength),
53
55
  * of kernel radius R, on the W × H native raster of `pitch` µm.
54
56
  */
55
- export function createDisplayViewLensPsf(psf, R, W, H, pitch) {
56
- const Z = Math.ceil(Math.max(W, H) / DISPLAY_VIEW_LENS_PSF_ZONES), zonesX = Math.ceil(W / Z), w = 2 * R + 1;
57
+ export function createDisplayViewLensPsf(psf, R, W, H, pitch, zones = DISPLAY_VIEW_LENS_PSF_ZONES) {
58
+ const Z = Math.ceil(Math.max(W, H) / zones), zonesX = Math.ceil(W / Z), w = 2 * R + 1;
57
59
  const zoneOf = (x, y) => Math.floor(y / Z) * zonesX + Math.floor(x / Z);
58
60
  const kernelsOf = (zone, wavelengthsNm) => {
59
61
  // The zone's centre in sites from the top-left corner (an edge zone may be narrower), in image millimetres (+Y up).
@@ -1 +1 @@
1
- {"version":3,"file":"display-view-lens-signal.js","sourceRoot":"","sources":["../../src/facade/display-view-lens-signal.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * The display view's expected signal with a lens field mapping (`lens.projection`, `lens.distortion`), `lens.vignetting` or\n * camera rotation (#563), in focus and with `lens.defocus` out of focus. Loaded on demand (a dynamic import in `runCapture`),\n * so a display view without these options, and a bundle that never asks for them, does not load it.\n *\n * What it computes. The capture's environment chain forms, for site (i, j) of CFA channel c,\n * μ_c(i, j) = Σ_o w_o · (1/T) Σ_t Σ_λ A_c(λ) Σ_k K_λ(k) · F(s) · L(D_t(s), λ), s = q_o(i, j) − k·p,\n * with q_o the query point of offset o (pixel-aperture node minus anti-aliasing split), K_λ the site kernel (diffraction, the\n * defocus disc or both; a single unit tap without them), D_t the scene ray of sensor point s at temporal midpoint t (inverse\n * distortion, the declared projection, the camera rotation at t), F = T·A its field factor (vignetting throughput × distortion\n * area factor) and A_c(λ) the electrons per unit spectral radiance on the axis (the display view's channel response, ideal\n * optics). In focus with a kernel this is the environment PSF quadrature (the field factor applied once at the source point,\n * before the PSF spreads the light); out of focus it is #548's image-space disc, the same sum in another order\n * (`defocus-image-space-provider.ts`); without a kernel it is the environment's own per-query sum. Only the scene access changes:\n * the readout, the estimators, the demosaic and the development run unchanged on these site values.\n *\n * Scene points. Without a kernel each query point is formed with the environment's own arithmetic (the site centre, aperture node\n * and split offset of `native-environment-lean.ts`), then `lookOf` (the environment's mapping, rotation and field factor,\n * #548) and the planar provider's plane-point arithmetic, so a point exactly on a chart boundary resolves as in the capture.\n * With a kernel the sources are the site lattice of each fractional offset, with #548's lattice formula. Kernels, materials and\n * per-material sums are the display view's own tables (`displayViewSignalTables`), shared with the rectilinear path.\n *\n * Caches (memory only, never values): site values in a ring of native rows across windows, and with a kernel each lattice\n * point's material (or radiance at each node) and field factor per lattice group and temporal midpoint, in a two-dimensional\n * ring tagged with the point, sized from the window and capped at LATTICE_CACHE_LIMIT entries (beyond it, points are\n * evaluated as they are read).\n *\n * Field-dependent PSF (#569, `lens.catalogue`; {@link createDisplayViewLensPsf}). The capture's environment PSF quadrature resolves the\n * catalogue lens's sampled PSF at each query point's own field position. The view cuts the native raster into square zones of\n * Z = ⌈max(W, H) / DISPLAY_VIEW_LENS_PSF_ZONES⌉ sites (one site on frames of at most that many sites a side) and every site of a zone\n * takes the PSF the capture's own resolver gives at the zone's centre, at each spectral node (an approximation: the PSF's change\n * across half a zone). A profile kernel's rows run with image +Y (up) and its tap (i, j) reads (x − (i − c)·p, y + (j − c)·p) in\n * native coordinates (`sensorPsfSourcePoint`), so the view's kernel (reading in(x − t)) is the profile kernel flipped vertically.\n * Each zone's combined kernels are the expected signal's own tables (`buildTables`) with the zone's kernels, built when a site of\n * the zone is first read and kept per input in a least-recently-used cache of at most 64 MB (at least four zones).\n *\n * Large defocus kernels (#564, `input.largeKernel`, radius above 64 sites). The image-space disc D is the same at every lattice\n * group, spectral node and temporal midpoint, so it commutes with those sums as in the rectilinear signal (`expected-signal.ts`):\n * μ_c(x) = Σ_s D(s)·E_c(x − s), with E_c(x) the sum above through the in-focus kernels (each node's diffraction kernel, or a unit\n * tap) at site position x for channel c, whatever x's own channel. E is computed in fixed 64-site tiles (all three channels, each\n * group's lattice points mapped once per tile and midpoint), and D ⊛ E_c by runs (`site-kernel-runs.ts`) in fixed 128-site tiles,\n * each site taking its own channel: every value depends only on its site, so regions and parts equal the whole view.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { createSiteKernelRunsLattice, type SiteKernelRunsRowPattern } from \"../optics/site-kernel-runs.js\";\nimport type { PreparedDefocusImageSpaceGeometry } from \"./defocus-image-space-provider.js\";\nimport { resolveLensSampledPsfKernel, type ResolveLensSampledPsfInput } from \"../optics/lens-psf-profile.js\";\nimport { buildTables, displayViewSignalTables, type DisplayViewExpectedSignal, type DisplayViewExpectedSignalInput, type GroupTables } from \"./expected-signal.js\";\n\n/** #569: field zones along the native raster's longer side. */\nexport const DISPLAY_VIEW_LENS_PSF_ZONES = 64;\n\n/** #569: a field-dependent PSF for the display view (see the module comment). */\nexport interface DisplayViewLensPsf {\n /** Kernel radius and zone side, in sites. */\n readonly radius: number;\n readonly zoneSites: number;\n /** The kernels at the frame centre's zone, for the expected-signal input's lattice groups and reach. */\n axisKernels(wavelengthsNm: readonly number[]): { radius: number; perNode: Float64Array[] };\n /** The combined kernels of the zone of native site (x, y), for an input whose kernels are the axis kernels. */\n tables(input: DisplayViewExpectedSignalInput): (x: number, y: number) => readonly GroupTables[];\n}\n\n/**\n * #569: the field-dependent PSF of a display view from the sampled PSF the capture resolves (everything but the field point and wavelength),\n * of kernel radius R, on the W × H native raster of `pitch` µm.\n */\nexport function createDisplayViewLensPsf(psf: Omit<ResolveLensSampledPsfInput, \"fieldPointMm\" | \"wavelengthNm\">, R: number, W: number, H: number, pitch: number): DisplayViewLensPsf {\n const Z = Math.ceil(Math.max(W, H) / DISPLAY_VIEW_LENS_PSF_ZONES), zonesX = Math.ceil(W / Z), w = 2 * R + 1;\n const zoneOf = (x: number, y: number): number => Math.floor(y / Z) * zonesX + Math.floor(x / Z);\n const kernelsOf = (zone: number, wavelengthsNm: readonly number[]): Float64Array[] => {\n // The zone's centre in sites from the top-left corner (an edge zone may be narrower), in image millimetres (+Y up).\n const zx = zone % zonesX, zy = (zone - zx) / zonesX, fieldPointMm = { x: ((zx * Z + Math.min(W, zx * Z + Z)) / 2 - W / 2) * pitch / 1000,\n y: (H / 2 - (zy * Z + Math.min(H, zy * Z + Z)) / 2) * pitch / 1000 };\n return wavelengthsNm.map((wavelengthNm) => {\n // Every node of the engine-built profile has the same (2R + 1)² window, so every resolved kernel has it too.\n const values = resolveLensSampledPsfKernel({ ...psf, fieldPointMm, wavelengthNm } as ResolveLensSampledPsfInput).normalizedIntensity, out = new Float64Array(w * w);\n for (let j = 0; j < w; j++) for (let i = 0; i < w; i++) out[(w - 1 - j) * w + i] = values[j * w + i]!;\n return out;\n });\n };\n const caches = new WeakMap<DisplayViewExpectedSignalInput, (x: number, y: number) => readonly GroupTables[]>();\n return { radius: R, zoneSites: Z,\n axisKernels: (wavelengthsNm) => ({ radius: R, perNode: kernelsOf(zoneOf(W >> 1, H >> 1), wavelengthsNm) }),\n tables(input): (x: number, y: number) => readonly GroupTables[] {\n let read = caches.get(input);\n if (read) return read;\n const cache = new Map<number, readonly GroupTables[]>();\n let kept = 0, last = -1, lastTables: readonly GroupTables[] = [];\n read = (x, y): readonly GroupTables[] => {\n const zone = zoneOf(x, y);\n if (zone === last) return lastTables;\n let tables = cache.get(zone);\n if (tables) cache.delete(zone);\n else {\n tables = buildTables({ ...input, kernels: { radius: R, perNode: kernelsOf(zone, input.wavelengthsNm) } }).groups;\n // Zones kept: at least 4, and at most 64 MB of them (every zone's tables have the same size).\n kept ||= Math.max(4, (1 << 23) / tables.reduce((n, g) => n + g.cw * g.ch * (g.neutral.length + g.spectral.flat().length + g.perNode.flat().length), 0));\n if (cache.size >= kept) cache.delete(cache.keys().next().value!);\n }\n cache.set(zone, tables); last = zone; lastTables = tables;\n return tables;\n };\n caches.set(input, read);\n return read;\n } };\n}\n\n/** What the lens signal needs from the resolved request. */\nexport interface DisplayViewLensSetup {\n geometry: PreparedDefocusImageSpaceGeometry;\n /** Temporal midpoints, seconds from exposure start: (i + 0.5)·shutter/T with camera rotation, [0] without. */\n times: readonly number[];\n /** The planar provider's plane distance and frame-unit scale. */\n distanceM: number;\n metresPerFrameUnit: number;\n pitch: number;\n imagingArea: { widthMm: number; heightMm: number };\n boxSamples: number;\n /** Anti-aliasing split spots (or one zero spot), in the order of the expected signal's offsets within each aperture node. */\n spots: readonly { offsetMicrometers: { x: number; y: number } }[];\n /**\n * #569: a field-dependent lens PSF (`lens.catalogue`, {@link createDisplayViewLensPsf}): each site reads its field zone's kernels\n * instead of the input's. The input's kernels (the axis zone's) set the lattice groups and the reach; absent, every site reads them.\n */\n psf?: DisplayViewLensPsf | undefined;\n /**\n * #569 (catalogue fisheyes): a ray that does not point toward the scene plane sees no scene (zero radiance), as the capture's provider\n * with `zeroBeyondHorizon` gives it, instead of failing.\n */\n zeroBeyondHorizon?: boolean | undefined;\n}\n\n/** Largest lattice cache, in entries over all lattice groups and temporal midpoints (times the spectral nodes for radiance scenes). */\nconst LATTICE_CACHE_LIMIT = 1 << 22;\n\nconst pow2 = (n: number): number => { let p = 1; while (p < n) p *= 2; return p; };\n\n/**\n * Checks that the mapping and the vignetting profile cover the farthest source point the view reads, (W/2 + reachSites, H/2 + reachSites)\n * sites from the axis at each corner (reachSites: the kernel radius plus the largest query offset, less the half site to the outer site\n * centre), and returns the factory of the view's expected signal for this request.\n */\nexport function prepareDisplayViewLensSignal(lens: DisplayViewLensSetup, nativeWidth: number, nativeHeight: number, reachSites: number, options: string):\n (input: DisplayViewExpectedSignalInput, spanColumns?: number) => DisplayViewExpectedSignal {\n const xMm = (nativeWidth / 2 + reachSites) * lens.pitch / 1000, yMm = (nativeHeight / 2 + reachSites) * lens.pitch / 1000;\n for (const t of lens.times) for (const [x, y] of [[-xMm, -yMm], [xMm, -yMm], [-xMm, yMm], [xMm, yMm]] as const) {\n try { if (!(lens.geometry.lookOf(x, y, t).z > 0) && !lens.zeroBeyondHorizon) throw new InvalidConfigurationError(\"its ray does not point toward the scene plane.\"); } catch (error) {\n throw new InvalidConfigurationError(\"simulateDisplayView with \" + options + \" reads the scene through the lens up to \" + (reachSites + 0.5) + \" sites beyond the native \" +\n \"raster's outer site centres (the kernel radius and the query offsets), and there (\" + Math.hypot(x, y).toFixed(3) + \" mm from the axis) \" + (error as Error).message);\n }\n }\n return (input, spanColumns = Infinity) => createLensSignal(lens, input, spanColumns);\n}\n\nfunction createLensSignal(lens: DisplayViewLensSetup, input: DisplayViewExpectedSignalInput, spanColumns: number): DisplayViewExpectedSignal {\n const W = input.nativeWidth, H = input.nativeHeight, nodes = input.wavelengthsNm.length, T = lens.times.length, times = lens.times;\n const { geometry, distanceM: distance, metresPerFrameUnit: scale, pitch, imagingArea } = lens;\n const mmPerSite = pitch / 1000, scene = input.scene, offsets = input.offsets, A = input.electronsPerRadiance, channelAt = input.channelAt;\n const materials = scene.kind === \"materials\" ? scene : undefined, radianceAt = scene.kind === \"radiance\" ? scene.radianceAt : undefined;\n const { reflectance, spectralIndex, neutralDirect, spectralDirect, groups } = displayViewSignalTables(input);\n const kernels = input.kernels, R = kernels ? kernels.radius : 0;\n /** #569: the combined kernels of the zone of site (x, y), or the input's own without a field-dependent PSF. */\n const zoneTables = lens.psf ? lens.psf.tables(input) : (): typeof groups => groups;\n let lookups = 0;\n // The plane point (frame units) and field factor of native sensor point (x, y) mm at time t: the environment's mapping (lookOf) and\n // the planar provider's own arithmetic for the outgoing direction −look.\n // #569: with zeroBeyondHorizon, a ray at or beyond 90° reads the plane's origin with a zero factor (zero radiance; `beyond` is set).\n let pu = 0, pv = 0, pf = 0, beyond = false;\n const zeroBeyond = lens.zeroBeyondHorizon === true;\n const map = (xMm: number, yMm: number, t: number): void => {\n const look = geometry.lookOf(xMm, yMm, t);\n beyond = !(look.z > 0);\n if (beyond) {\n if (!zeroBeyond || !Number.isFinite(look.z)) throw new InvalidConfigurationError(\"simulateDisplayView: a query ray does not point toward the scene plane.\");\n pu = 0; pv = 0; pf = 0;\n return;\n }\n const s = distance / look.z;\n pu = look.x * s / scale; pv = look.y * s / scale; pf = look.factor;\n };\n const materialOf = (m: number): number => { if (spectralIndex[m] === undefined) throw new InvalidConfigurationError(\"Unknown chart material.\"); return m; };\n // Without a kernel: the environment's query point of offset o of site (x, y) (native-environment-lean.ts, as buildExpectedSignalInput's queryPoint).\n const box = lens.boxSamples, siteWidthMm = pitch / 1000;\n const phases = offsets.map((_, o) => {\n const node = Math.floor(o / lens.spots.length), spot = lens.spots[o % lens.spots.length]!.offsetMicrometers;\n return { xPhase: (node % box + 0.5) / box, yPhase: (Math.floor(node / box) + 0.5) / box, aaX: spot.x / 1000, aaY: spot.y / 1000 };\n });\n function directSite(x: number, y: number): number {\n const c = channelAt(x, y), centerX = -imagingArea.widthMm / 2 + (pitch / 2 + x * pitch + 0) / 1000, centerY = -imagingArea.heightMm / 2 + (pitch / 2 + y * pitch + 0) / 1000;\n let total = 0;\n for (let ti = 0; ti < T; ti++) {\n let sum = 0;\n for (let o = 0; o < offsets.length; o++) {\n const node = phases[o]!;\n map((centerX - siteWidthMm / 2 + node.xPhase * siteWidthMm) - node.aaX, (centerY - siteWidthMm / 2 + node.yPhase * siteWidthMm) - node.aaY, times[ti]!);\n let value: number;\n if (materials) {\n const m = materialOf(materials.materialAt(pu, pv)), si = spectralIndex[m]!;\n value = si < 0 ? reflectance[m]! * neutralDirect[c]! : spectralDirect[c]![si]!; lookups++;\n } else { value = 0; for (let n = 0; n < nodes; n++) value += A[c]![n]! * radianceAt!(pu, pv, input.wavelengthsNm[n]!); lookups += nodes; }\n sum += offsets[o]!.weight * (pf * value);\n }\n total += sum;\n }\n return total / T;\n }\n // With a kernel: lattice point (p, q) of group g at time t, #548's lattice formula, cached in a ring tagged with (p, q).\n const G = groups.length, slots = G * T, per = materials ? 1 : nodes;\n let cacheRows = 0, cacheCols = 0, tagQ = new Int32Array(0), tagP = new Int32Array(0), cacheMaterial = new Int32Array(0), cacheFactor = new Float64Array(0), cacheRadiance = new Float64Array(0);\n const radiance = new Float64Array(nodes);\n let lm = 0, lf = 0;\n function lattice(g: number, ti: number, p: number, q: number): void {\n let k = -1;\n if (cacheRows > 0) {\n k = ((g * T + ti) * cacheRows + (q & (cacheRows - 1))) * cacheCols + (p & (cacheCols - 1));\n if (tagQ[k] === q && tagP[k] === p) {\n lf = cacheFactor[k]!;\n if (materials) lm = cacheMaterial[k]!; else for (let n = 0; n < nodes; n++) radiance[n] = cacheRadiance[k * nodes + n]!;\n return;\n }\n }\n const group = groups[g]!;\n map((p + 0.5 + group.fx - W / 2) * mmPerSite, (q + 0.5 + group.fy - H / 2) * mmPerSite, times[ti]!);\n lf = pf;\n if (materials) { lm = materialOf(materials.materialAt(pu, pv)); lookups++; }\n else { for (let n = 0; n < nodes; n++) radiance[n] = radianceAt!(pu, pv, input.wavelengthsNm[n]!); lookups += nodes; }\n if (k >= 0) {\n tagQ[k] = q; tagP[k] = p; cacheFactor[k] = lf;\n if (materials) cacheMaterial[k] = lm; else for (let n = 0; n < nodes; n++) cacheRadiance[k * nodes + n] = radiance[n]!;\n }\n }\n function kernelSite(x: number, y: number): number {\n const c = channelAt(x, y), rowMask = cacheRows - 1, colMask = cacheCols - 1, zone = zoneTables(x, y);\n let total = 0;\n for (let ti = 0; ti < T; ti++) {\n let sum = 0;\n for (let g = 0; g < G; g++) {\n const group = groups[g]!, p0 = x + group.minIx - R, q0 = y + group.minIy - R, cw = group.cw, ch = group.ch, weights = zone[g]!;\n if (materials) {\n const nk = weights.neutral[c]!, sk = weights.spectral[c]!;\n for (let dy = 0, t = 0; dy < ch; dy++) {\n // The cache row of lattice row q (read inline: the common case is a hit).\n const q = q0 + dy, row = cacheRows > 0 ? ((g * T + ti) * cacheRows + (q & rowMask)) * cacheCols : -1;\n for (let dx = 0; dx < cw; dx++, t++) {\n const p = p0 + dx, k = row + (p & colMask);\n if (row >= 0 && tagQ[k] === q && tagP[k] === p) { lm = cacheMaterial[k]!; lf = cacheFactor[k]!; } else lattice(g, ti, p, q);\n const si = spectralIndex[lm]!;\n sum += lf * (si < 0 ? reflectance[lm]! * nk[t]! : sk[si]![t]!);\n }\n }\n } else for (let dy = 0, t = 0; dy < ch; dy++) for (let dx = 0; dx < cw; dx++, t++) {\n lattice(g, ti, p0 + dx, q0 + dy);\n let value = 0;\n for (let n = 0; n < nodes; n++) value += weights.perNode[n]![c]![t]! * radiance[n]!;\n sum += lf * value;\n }\n }\n total += sum;\n }\n return total / T;\n }\n const pilotNode = input.wavelengthsNm[Math.floor(nodes / 2)]!;\n if (input.largeKernel) return createLargeLensSignal(input, inFocusLensTile, () => lookups, pilot);\n /** E_c (#564) of the native site positions [x0, x0 + T) × [y0, y0 + T) for the three channels: kernelSite's sum for each channel. */\n function inFocusLensTile(x0: number, y0: number, TS: number): Float64Array[] {\n const out = [0, 1, 2].map(() => new Float64Array(TS * TS));\n // A fixed tile reaches past the raster: positions more than the disc's radius beyond it feed no site, so they stay 0 and are never\n // mapped (the lens profiles are checked only up to the view's reach).\n const D = input.largeKernel!.radius;\n if (x0 + TS <= -D || x0 >= W + D || y0 + TS <= -D || y0 >= H + D) return out;\n if (x0 < -D || x0 + TS > W + D || y0 < -D || y0 + TS > H + D) {\n const xa = Math.max(x0, -D), xb = Math.min(x0 + TS, W + D), ya = Math.max(y0, -D), yb = Math.min(y0 + TS, H + D);\n const part = inFocusLensRect(xa, ya, xb - xa, yb - ya);\n for (let c = 0; c < 3; c++) for (let y = ya; y < yb; y++) out[c]!.set(part[c]!.subarray((y - ya) * (xb - xa), (y - ya + 1) * (xb - xa)), (y - y0) * TS + xa - x0);\n return out;\n }\n return inFocusLensRect(x0, y0, TS, TS);\n }\n /** E_c of the native site positions [x0, x0 + w) × [y0, y0 + h), row-major, for the three channels. */\n function inFocusLensRect(x0: number, y0: number, TW: number, TH: number): Float64Array[] {\n const out = [0, 1, 2].map(() => new Float64Array(TW * TH)), sum = [0, 1, 2].map(() => new Float64Array(TW * TH));\n for (let ti = 0; ti < T; ti++) {\n for (const e of sum) e.fill(0);\n for (const group of groups) {\n const cw = group.cw, ch = group.ch, gw = TW + cw - 1, gh = TH + ch - 1, p0 = x0 + group.minIx - R, q0 = y0 + group.minIy - R;\n const factor = new Float64Array(gw * gh), material = materials ? new Int32Array(gw * gh) : undefined, values = materials ? undefined : new Float64Array(gw * gh * nodes);\n for (let j = 0; j < gh; j++) for (let i = 0; i < gw; i++) {\n const k = j * gw + i;\n map((p0 + i + 0.5 + group.fx - W / 2) * mmPerSite, (q0 + j + 0.5 + group.fy - H / 2) * mmPerSite, times[ti]!);\n factor[k] = pf;\n if (material) material[k] = materialOf(materials!.materialAt(pu, pv));\n else for (let n = 0; n < nodes; n++) values![k * nodes + n] = radianceAt!(pu, pv, input.wavelengthsNm[n]!);\n }\n lookups += material ? gw * gh : gw * gh * nodes;\n for (let c = 0; c < 3; c++) {\n const e = sum[c]!, nk = group.neutral[c], sk = group.spectral[c];\n for (let y = 0; y < TH; y++) for (let x = 0; x < TW; x++) {\n let v = 0;\n for (let dy = 0, t = 0; dy < ch; dy++) for (let dx = 0; dx < cw; dx++, t++) {\n const k = (y + dy) * gw + x + dx;\n if (material) { const m = material[k]!, si = spectralIndex[m]!; v += factor[k]! * (si < 0 ? reflectance[m]! * nk![t]! : sk![si]![t]!); }\n else { let r = 0; for (let n = 0; n < nodes; n++) r += group.perNode[n]![c]![t]! * values![k * nodes + n]!; v += factor[k]! * r; }\n }\n e[y * TW + x] = e[y * TW + x]! + v;\n }\n }\n }\n for (let c = 0; c < 3; c++) { const o = out[c]!, e = sum[c]!; for (let k = 0; k < o.length; k++) o[k] = o[k]! + e[k]!; }\n }\n for (const o of out) for (let k = 0; k < o.length; k++) o[k] = o[k]! / T;\n return out;\n }\n // Site values persist across windows in a ring of native rows (a site's value does not depend on the window).\n let ringRows = 0, ring = new Float64Array(0), ringRowId = new Int32Array(0), ringOn = false;\n const compute = kernels ? kernelSite : directSite;\n return {\n get lookups(): number { return lookups; },\n uniformMaterial: -1,\n tracksMaterial: false,\n get cachesSites(): boolean { return ringOn; },\n marksReads: false,\n markReads(): void { /* never called: marksReads is false */ },\n window(x0: number, y0: number, x1: number, y1: number): void {\n const sw = Math.max(0, x1 - x0), sh = Math.max(0, y1 - y0);\n if (sh > 0 && ringRows < 2 * sh) {\n const rows = pow2(2 * sh);\n if (rows * W <= LATTICE_CACHE_LIMIT) { ringRows = rows; ring = new Float64Array(rows * W).fill(NaN); ringRowId = new Int32Array(rows).fill(-1); }\n }\n ringOn = sh > 0 && ringRows >= 2 * sh;\n if (!kernels || sw === 0) return;\n // The lattice rectangle the window's sites read, per group; the cache keeps two such heights and the columns the render's windows span.\n let cw = 0, ch = 0;\n for (const group of groups) { cw = Math.max(cw, group.cw); ch = Math.max(ch, group.ch); }\n const height = sh + ch - 1, width = sw + cw - 1;\n let rows = pow2(2 * height), cols = pow2(Math.min(W + 2 * (R + cw), Math.max(width, (Number.isFinite(spanColumns) ? spanColumns : W) + width)));\n if (slots * per * rows * cols > LATTICE_CACHE_LIMIT) rows = pow2(height);\n if (slots * per * rows * cols > LATTICE_CACHE_LIMIT) cols = pow2(width);\n if (slots * per * rows * cols > LATTICE_CACHE_LIMIT) { cacheRows = 0; return; }\n if (rows > cacheRows || cols > cacheCols) {\n rows = Math.max(rows, cacheRows); cols = Math.max(cols, cacheCols);\n if (slots * per * rows * cols > LATTICE_CACHE_LIMIT) { rows = pow2(height); cols = pow2(width); }\n cacheRows = rows; cacheCols = cols;\n const size = slots * rows * cols;\n tagQ = new Int32Array(size).fill(-2147483648); tagP = new Int32Array(size); cacheFactor = new Float64Array(size);\n if (materials) cacheMaterial = new Int32Array(size); else cacheRadiance = new Float64Array(size * nodes);\n }\n },\n site(x: number, y: number): number {\n if (!ringOn) return compute(x, y);\n const slot = y & (ringRows - 1), k = slot * W + x;\n if (ringRowId[slot] === y) { const v = ring[k]!; if (v === v) return v; }\n else { ringRowId[slot] = y; ring.fill(NaN, slot * W, (slot + 1) * W); }\n const v = compute(x, y);\n ring[k] = v;\n return v;\n },\n pilot\n };\n /**\n * The renderer's pilot point is a rectilinear plane point of the native raster: back to the sensor point, then through the lens at\n * every temporal midpoint. A point whose scene value differs between the instants (motion) counts as detail (NaN equals nothing).\n */\n function pilot(u: number, v: number): number {\n const g = 2 / input.outputWidth, xMm = u / g * mmPerSite, yMm = -v / g * mmPerSite;\n let first = NaN;\n try {\n for (let ti = 0; ti < T; ti++) {\n map(xMm, yMm, times[ti]!);\n const value = beyond ? -1 : materials ? materials.materialAt(pu, pv) : radianceAt!(pu, pv, pilotNode);\n lookups++;\n if (ti === 0) first = value; else if (value !== first) return NaN;\n }\n } catch { return NaN; }\n return first;\n }\n}\n\n/** #564: tile sides of the large-kernel lens signal (the in-focus E and the convolved sites) and the bytes each tile cache keeps. */\nconst LARGE_E_TILE = 64, LARGE_OUTPUT_TILE = 128, LARGE_CACHE_BYTES = 32 * 1048576;\n\n/** #564: the lens signal with a defocus kernel above 64 sites: D ⊛ E_c by runs over the in-focus tiles (see the module comment). */\nfunction createLargeLensSignal(input: DisplayViewExpectedSignalInput, inFocusTile: (x0: number, y0: number, T: number) => Float64Array[], lookups: () => number,\n pilot: (u: number, v: number) => number): DisplayViewExpectedSignal {\n const runs = input.largeKernel!, channelAt = input.channelAt, TE = LARGE_E_TILE;\n // At least the in-focus tiles one output tile's source spans plus one more row of them, so the next output tile of a row reuses them.\n const span = Math.ceil((LARGE_OUTPUT_TILE + 2 * runs.radius) / TE) + 1;\n const inFocus = new Map<number, Float64Array[]>(), capacity = Math.max(span * (span + 1), Math.floor(LARGE_CACHE_BYTES / (3 * TE * TE * 8)));\n const tileAt = (tx: number, ty: number): Float64Array[] => {\n const key = (ty + 1048576) * 2097152 + tx + 1048576;\n let tile = inFocus.get(key);\n if (tile) { inFocus.delete(key); inFocus.set(key, tile); }\n else {\n tile = inFocusTile(tx * TE, ty * TE, TE);\n inFocus.set(key, tile);\n if (inFocus.size > capacity) inFocus.delete(inFocus.keys().next().value!);\n }\n return tile;\n };\n // Which sites of a tile row hold channel c: the CFA's 2 × 2 period (tile origins are even).\n const phase = [0, 1].map((py) => [0, 1].map((px) => channelAt(px, py)));\n const patterns: SiteKernelRunsRowPattern[] = [0, 1, 2].map((c) => (row: number) => {\n const p = phase[row & 1]!, even = p[0] === c, odd = p[1] === c;\n return even && odd ? { start: 0, step: 1 } : even ? { start: 0, step: 2 } : odd ? { start: 1, step: 2 } : null;\n });\n const lattice = createSiteKernelRunsLattice({ runs, tile: LARGE_OUTPUT_TILE, fields: 3, capacityBytes: LARGE_CACHE_BYTES, pattern: (c) => patterns[c],\n source: (x0, y0, width, height) => (c: number): Float64Array => {\n const samples = new Float64Array(width * height);\n for (let ty = Math.floor(y0 / TE); ty * TE < y0 + height; ty++) for (let tx = Math.floor(x0 / TE); tx * TE < x0 + width; tx++) {\n const tile = tileAt(tx, ty)[c]!, ax = Math.max(x0, tx * TE), bx = Math.min(x0 + width, (tx + 1) * TE), ay = Math.max(y0, ty * TE), by = Math.min(y0 + height, (ty + 1) * TE);\n for (let y = ay; y < by; y++) samples.set(tile.subarray((y - ty * TE) * TE + ax - tx * TE, (y - ty * TE) * TE + bx - tx * TE), (y - y0) * width + ax - x0);\n }\n return samples;\n } });\n return {\n get lookups(): number { return lookups(); },\n uniformMaterial: -1,\n tracksMaterial: false,\n cachesSites: false,\n marksReads: false,\n markReads(): void { /* never called: marksReads is false */ },\n window(): void { /* the tiles are fixed and kept for the signal; a window changes nothing */ },\n site(x: number, y: number): number { return lattice.valueAt(channelAt(x, y), x, y); },\n pilot\n };\n}\n"]}
1
+ {"version":3,"file":"display-view-lens-signal.js","sourceRoot":"","sources":["../../src/facade/display-view-lens-signal.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * The display view's expected signal with a lens field mapping (`lens.projection`, `lens.distortion`), `lens.vignetting` or\n * camera rotation (#563), in focus and with `lens.defocus` out of focus. Loaded on demand (a dynamic import in `runCapture`),\n * so a display view without these options, and a bundle that never asks for them, does not load it.\n *\n * What it computes. The capture's environment chain forms, for site (i, j) of CFA channel c,\n * μ_c(i, j) = Σ_o w_o · (1/T) Σ_t Σ_λ A_c(λ) Σ_k K_λ(k) · F(s) · L(D_t(s), λ), s = q_o(i, j) − k·p,\n * with q_o the query point of offset o (pixel-aperture node minus anti-aliasing split), K_λ the site kernel (diffraction, the\n * defocus disc or both; a single unit tap without them), D_t the scene ray of sensor point s at temporal midpoint t (inverse\n * distortion, the declared projection, the camera rotation at t), F = T·A its field factor (vignetting throughput × distortion\n * area factor) and A_c(λ) the electrons per unit spectral radiance on the axis (the display view's channel response, ideal\n * optics). In focus with a kernel this is the environment PSF quadrature (the field factor applied once at the source point,\n * before the PSF spreads the light); out of focus it is #548's image-space disc, the same sum in another order\n * (`defocus-image-space-provider.ts`); without a kernel it is the environment's own per-query sum. Only the scene access changes:\n * the readout, the estimators, the demosaic and the development run unchanged on these site values.\n *\n * Scene points. Without a kernel each query point is formed with the environment's own arithmetic (the site centre, aperture node\n * and split offset of `native-environment-lean.ts`), then `lookOf` (the environment's mapping, rotation and field factor,\n * #548) and the planar provider's plane-point arithmetic, so a point exactly on a chart boundary resolves as in the capture.\n * With a kernel the sources are the site lattice of each fractional offset, with #548's lattice formula. Kernels, materials and\n * per-material sums are the display view's own tables (`displayViewSignalTables`), shared with the rectilinear path.\n *\n * Caches (memory only, never values): site values in a ring of native rows across windows, and with a kernel each lattice\n * point's material (or radiance at each node) and field factor per lattice group and temporal midpoint, in a two-dimensional\n * ring tagged with the point, sized from the window and capped at LATTICE_CACHE_LIMIT entries (beyond it, points are\n * evaluated as they are read).\n *\n * Field-dependent PSF (#569, `lens.catalogue`; {@link createDisplayViewLensPsf}). The capture's environment PSF quadrature resolves the\n * catalogue lens's sampled PSF at each query point's own field position. The view cuts the native raster into square zones of\n * Z = ⌈max(W, H) / DISPLAY_VIEW_LENS_PSF_ZONES⌉ sites (one site on frames of at most that many sites a side) and every site of a zone\n * takes the PSF the capture's own resolver gives at the zone's centre, at each spectral node (an approximation: the PSF's change\n * across half a zone). A profile kernel's rows run with image +Y (up) and its tap (i, j) reads (x − (i − c)·p, y + (j − c)·p) in\n * native coordinates (`sensorPsfSourcePoint`), so the view's kernel (reading in(x − t)) is the profile kernel flipped vertically.\n * Each zone's combined kernels are the expected signal's own tables (`buildTables`) with the zone's kernels, built when a site of\n * the zone is first read and kept per input in a least-recently-used cache of at most 64 MB (at least four zones). The zones are the\n * view's fast method for `lens.catalogue` (2.20.0); its exact method (`fast: false`) passes `zones` = max(W, H), one site per zone,\n * the capture's own PSF at each site centre (much slower).\n *\n * Large defocus kernels (#564, `input.largeKernel`, radius above 64 sites). The image-space disc D is the same at every lattice\n * group, spectral node and temporal midpoint, so it commutes with those sums as in the rectilinear signal (`expected-signal.ts`):\n * μ_c(x) = Σ_s D(s)·E_c(x − s), with E_c(x) the sum above through the in-focus kernels (each node's diffraction kernel, or a unit\n * tap) at site position x for channel c, whatever x's own channel. E is computed in fixed 64-site tiles (all three channels, each\n * group's lattice points mapped once per tile and midpoint), and D ⊛ E_c by runs (`site-kernel-runs.ts`) in fixed 128-site tiles,\n * each site taking its own channel: every value depends only on its site, so regions and parts equal the whole view.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { createSiteKernelRunsLattice, type SiteKernelRunsRowPattern } from \"../optics/site-kernel-runs.js\";\nimport type { PreparedDefocusImageSpaceGeometry } from \"./defocus-image-space-provider.js\";\nimport { resolveLensSampledPsfKernel, type ResolveLensSampledPsfInput } from \"../optics/lens-psf-profile.js\";\nimport { buildTables, displayViewSignalTables, type DisplayViewExpectedSignal, type DisplayViewExpectedSignalInput, type GroupTables } from \"./expected-signal.js\";\n\n/** #569: field zones along the native raster's longer side. */\nexport const DISPLAY_VIEW_LENS_PSF_ZONES = 64;\n\n/** #569: a field-dependent PSF for the display view (see the module comment). */\nexport interface DisplayViewLensPsf {\n /** Kernel radius and zone side, in sites. */\n readonly radius: number;\n readonly zoneSites: number;\n /** The kernels at the frame centre's zone, for the expected-signal input's lattice groups and reach. */\n axisKernels(wavelengthsNm: readonly number[]): { radius: number; perNode: Float64Array[] };\n /** The combined kernels of the zone of native site (x, y), for an input whose kernels are the axis kernels. */\n tables(input: DisplayViewExpectedSignalInput): (x: number, y: number) => readonly GroupTables[];\n}\n\n/**\n * #569: the field-dependent PSF of a display view from the sampled PSF the capture resolves (everything but the field point and wavelength),\n * of kernel radius R, on the W × H native raster of `pitch` µm.\n */\nexport function createDisplayViewLensPsf(psf: Omit<ResolveLensSampledPsfInput, \"fieldPointMm\" | \"wavelengthNm\">, R: number, W: number, H: number, pitch: number,\n zones = DISPLAY_VIEW_LENS_PSF_ZONES): DisplayViewLensPsf {\n const Z = Math.ceil(Math.max(W, H) / zones), zonesX = Math.ceil(W / Z), w = 2 * R + 1;\n const zoneOf = (x: number, y: number): number => Math.floor(y / Z) * zonesX + Math.floor(x / Z);\n const kernelsOf = (zone: number, wavelengthsNm: readonly number[]): Float64Array[] => {\n // The zone's centre in sites from the top-left corner (an edge zone may be narrower), in image millimetres (+Y up).\n const zx = zone % zonesX, zy = (zone - zx) / zonesX, fieldPointMm = { x: ((zx * Z + Math.min(W, zx * Z + Z)) / 2 - W / 2) * pitch / 1000,\n y: (H / 2 - (zy * Z + Math.min(H, zy * Z + Z)) / 2) * pitch / 1000 };\n return wavelengthsNm.map((wavelengthNm) => {\n // Every node of the engine-built profile has the same (2R + 1)² window, so every resolved kernel has it too.\n const values = resolveLensSampledPsfKernel({ ...psf, fieldPointMm, wavelengthNm } as ResolveLensSampledPsfInput).normalizedIntensity, out = new Float64Array(w * w);\n for (let j = 0; j < w; j++) for (let i = 0; i < w; i++) out[(w - 1 - j) * w + i] = values[j * w + i]!;\n return out;\n });\n };\n const caches = new WeakMap<DisplayViewExpectedSignalInput, (x: number, y: number) => readonly GroupTables[]>();\n return { radius: R, zoneSites: Z,\n axisKernels: (wavelengthsNm) => ({ radius: R, perNode: kernelsOf(zoneOf(W >> 1, H >> 1), wavelengthsNm) }),\n tables(input): (x: number, y: number) => readonly GroupTables[] {\n let read = caches.get(input);\n if (read) return read;\n const cache = new Map<number, readonly GroupTables[]>();\n let kept = 0, last = -1, lastTables: readonly GroupTables[] = [];\n read = (x, y): readonly GroupTables[] => {\n const zone = zoneOf(x, y);\n if (zone === last) return lastTables;\n let tables = cache.get(zone);\n if (tables) cache.delete(zone);\n else {\n tables = buildTables({ ...input, kernels: { radius: R, perNode: kernelsOf(zone, input.wavelengthsNm) } }).groups;\n // Zones kept: at least 4, and at most 64 MB of them (every zone's tables have the same size).\n kept ||= Math.max(4, (1 << 23) / tables.reduce((n, g) => n + g.cw * g.ch * (g.neutral.length + g.spectral.flat().length + g.perNode.flat().length), 0));\n if (cache.size >= kept) cache.delete(cache.keys().next().value!);\n }\n cache.set(zone, tables); last = zone; lastTables = tables;\n return tables;\n };\n caches.set(input, read);\n return read;\n } };\n}\n\n/** What the lens signal needs from the resolved request. */\nexport interface DisplayViewLensSetup {\n geometry: PreparedDefocusImageSpaceGeometry;\n /** Temporal midpoints, seconds from exposure start: (i + 0.5)·shutter/T with camera rotation, [0] without. */\n times: readonly number[];\n /** The planar provider's plane distance and frame-unit scale. */\n distanceM: number;\n metresPerFrameUnit: number;\n pitch: number;\n imagingArea: { widthMm: number; heightMm: number };\n boxSamples: number;\n /** Anti-aliasing split spots (or one zero spot), in the order of the expected signal's offsets within each aperture node. */\n spots: readonly { offsetMicrometers: { x: number; y: number } }[];\n /**\n * #569: a field-dependent lens PSF (`lens.catalogue`, {@link createDisplayViewLensPsf}): each site reads its field zone's kernels\n * instead of the input's. The input's kernels (the axis zone's) set the lattice groups and the reach; absent, every site reads them.\n */\n psf?: DisplayViewLensPsf | undefined;\n /**\n * #569 (catalogue fisheyes): a ray that does not point toward the scene plane sees no scene (zero radiance), as the capture's provider\n * with `zeroBeyondHorizon` gives it, instead of failing.\n */\n zeroBeyondHorizon?: boolean | undefined;\n}\n\n/** Largest lattice cache, in entries over all lattice groups and temporal midpoints (times the spectral nodes for radiance scenes). */\nconst LATTICE_CACHE_LIMIT = 1 << 22;\n\nconst pow2 = (n: number): number => { let p = 1; while (p < n) p *= 2; return p; };\n\n/**\n * Checks that the mapping and the vignetting profile cover the farthest source point the view reads, (W/2 + reachSites, H/2 + reachSites)\n * sites from the axis at each corner (reachSites: the kernel radius plus the largest query offset, less the half site to the outer site\n * centre), and returns the factory of the view's expected signal for this request.\n */\nexport function prepareDisplayViewLensSignal(lens: DisplayViewLensSetup, nativeWidth: number, nativeHeight: number, reachSites: number, options: string):\n (input: DisplayViewExpectedSignalInput, spanColumns?: number) => DisplayViewExpectedSignal {\n const xMm = (nativeWidth / 2 + reachSites) * lens.pitch / 1000, yMm = (nativeHeight / 2 + reachSites) * lens.pitch / 1000;\n for (const t of lens.times) for (const [x, y] of [[-xMm, -yMm], [xMm, -yMm], [-xMm, yMm], [xMm, yMm]] as const) {\n try { if (!(lens.geometry.lookOf(x, y, t).z > 0) && !lens.zeroBeyondHorizon) throw new InvalidConfigurationError(\"its ray does not point toward the scene plane.\"); } catch (error) {\n throw new InvalidConfigurationError(\"simulateDisplayView with \" + options + \" reads the scene through the lens up to \" + (reachSites + 0.5) + \" sites beyond the native \" +\n \"raster's outer site centres (the kernel radius and the query offsets), and there (\" + Math.hypot(x, y).toFixed(3) + \" mm from the axis) \" + (error as Error).message);\n }\n }\n return (input, spanColumns = Infinity) => createLensSignal(lens, input, spanColumns);\n}\n\nfunction createLensSignal(lens: DisplayViewLensSetup, input: DisplayViewExpectedSignalInput, spanColumns: number): DisplayViewExpectedSignal {\n const W = input.nativeWidth, H = input.nativeHeight, nodes = input.wavelengthsNm.length, T = lens.times.length, times = lens.times;\n const { geometry, distanceM: distance, metresPerFrameUnit: scale, pitch, imagingArea } = lens;\n const mmPerSite = pitch / 1000, scene = input.scene, offsets = input.offsets, A = input.electronsPerRadiance, channelAt = input.channelAt;\n const materials = scene.kind === \"materials\" ? scene : undefined, radianceAt = scene.kind === \"radiance\" ? scene.radianceAt : undefined;\n const { reflectance, spectralIndex, neutralDirect, spectralDirect, groups } = displayViewSignalTables(input);\n const kernels = input.kernels, R = kernels ? kernels.radius : 0;\n /** #569: the combined kernels of the zone of site (x, y), or the input's own without a field-dependent PSF. */\n const zoneTables = lens.psf ? lens.psf.tables(input) : (): typeof groups => groups;\n let lookups = 0;\n // The plane point (frame units) and field factor of native sensor point (x, y) mm at time t: the environment's mapping (lookOf) and\n // the planar provider's own arithmetic for the outgoing direction −look.\n // #569: with zeroBeyondHorizon, a ray at or beyond 90° reads the plane's origin with a zero factor (zero radiance; `beyond` is set).\n let pu = 0, pv = 0, pf = 0, beyond = false;\n const zeroBeyond = lens.zeroBeyondHorizon === true;\n const map = (xMm: number, yMm: number, t: number): void => {\n const look = geometry.lookOf(xMm, yMm, t);\n beyond = !(look.z > 0);\n if (beyond) {\n if (!zeroBeyond || !Number.isFinite(look.z)) throw new InvalidConfigurationError(\"simulateDisplayView: a query ray does not point toward the scene plane.\");\n pu = 0; pv = 0; pf = 0;\n return;\n }\n const s = distance / look.z;\n pu = look.x * s / scale; pv = look.y * s / scale; pf = look.factor;\n };\n const materialOf = (m: number): number => { if (spectralIndex[m] === undefined) throw new InvalidConfigurationError(\"Unknown chart material.\"); return m; };\n // Without a kernel: the environment's query point of offset o of site (x, y) (native-environment-lean.ts, as buildExpectedSignalInput's queryPoint).\n const box = lens.boxSamples, siteWidthMm = pitch / 1000;\n const phases = offsets.map((_, o) => {\n const node = Math.floor(o / lens.spots.length), spot = lens.spots[o % lens.spots.length]!.offsetMicrometers;\n return { xPhase: (node % box + 0.5) / box, yPhase: (Math.floor(node / box) + 0.5) / box, aaX: spot.x / 1000, aaY: spot.y / 1000 };\n });\n function directSite(x: number, y: number): number {\n const c = channelAt(x, y), centerX = -imagingArea.widthMm / 2 + (pitch / 2 + x * pitch + 0) / 1000, centerY = -imagingArea.heightMm / 2 + (pitch / 2 + y * pitch + 0) / 1000;\n let total = 0;\n for (let ti = 0; ti < T; ti++) {\n let sum = 0;\n for (let o = 0; o < offsets.length; o++) {\n const node = phases[o]!;\n map((centerX - siteWidthMm / 2 + node.xPhase * siteWidthMm) - node.aaX, (centerY - siteWidthMm / 2 + node.yPhase * siteWidthMm) - node.aaY, times[ti]!);\n let value: number;\n if (materials) {\n const m = materialOf(materials.materialAt(pu, pv)), si = spectralIndex[m]!;\n value = si < 0 ? reflectance[m]! * neutralDirect[c]! : spectralDirect[c]![si]!; lookups++;\n } else { value = 0; for (let n = 0; n < nodes; n++) value += A[c]![n]! * radianceAt!(pu, pv, input.wavelengthsNm[n]!); lookups += nodes; }\n sum += offsets[o]!.weight * (pf * value);\n }\n total += sum;\n }\n return total / T;\n }\n // With a kernel: lattice point (p, q) of group g at time t, #548's lattice formula, cached in a ring tagged with (p, q).\n const G = groups.length, slots = G * T, per = materials ? 1 : nodes;\n let cacheRows = 0, cacheCols = 0, tagQ = new Int32Array(0), tagP = new Int32Array(0), cacheMaterial = new Int32Array(0), cacheFactor = new Float64Array(0), cacheRadiance = new Float64Array(0);\n const radiance = new Float64Array(nodes);\n let lm = 0, lf = 0;\n function lattice(g: number, ti: number, p: number, q: number): void {\n let k = -1;\n if (cacheRows > 0) {\n k = ((g * T + ti) * cacheRows + (q & (cacheRows - 1))) * cacheCols + (p & (cacheCols - 1));\n if (tagQ[k] === q && tagP[k] === p) {\n lf = cacheFactor[k]!;\n if (materials) lm = cacheMaterial[k]!; else for (let n = 0; n < nodes; n++) radiance[n] = cacheRadiance[k * nodes + n]!;\n return;\n }\n }\n const group = groups[g]!;\n map((p + 0.5 + group.fx - W / 2) * mmPerSite, (q + 0.5 + group.fy - H / 2) * mmPerSite, times[ti]!);\n lf = pf;\n if (materials) { lm = materialOf(materials.materialAt(pu, pv)); lookups++; }\n else { for (let n = 0; n < nodes; n++) radiance[n] = radianceAt!(pu, pv, input.wavelengthsNm[n]!); lookups += nodes; }\n if (k >= 0) {\n tagQ[k] = q; tagP[k] = p; cacheFactor[k] = lf;\n if (materials) cacheMaterial[k] = lm; else for (let n = 0; n < nodes; n++) cacheRadiance[k * nodes + n] = radiance[n]!;\n }\n }\n function kernelSite(x: number, y: number): number {\n const c = channelAt(x, y), rowMask = cacheRows - 1, colMask = cacheCols - 1, zone = zoneTables(x, y);\n let total = 0;\n for (let ti = 0; ti < T; ti++) {\n let sum = 0;\n for (let g = 0; g < G; g++) {\n const group = groups[g]!, p0 = x + group.minIx - R, q0 = y + group.minIy - R, cw = group.cw, ch = group.ch, weights = zone[g]!;\n if (materials) {\n const nk = weights.neutral[c]!, sk = weights.spectral[c]!;\n for (let dy = 0, t = 0; dy < ch; dy++) {\n // The cache row of lattice row q (read inline: the common case is a hit).\n const q = q0 + dy, row = cacheRows > 0 ? ((g * T + ti) * cacheRows + (q & rowMask)) * cacheCols : -1;\n for (let dx = 0; dx < cw; dx++, t++) {\n const p = p0 + dx, k = row + (p & colMask);\n if (row >= 0 && tagQ[k] === q && tagP[k] === p) { lm = cacheMaterial[k]!; lf = cacheFactor[k]!; } else lattice(g, ti, p, q);\n const si = spectralIndex[lm]!;\n sum += lf * (si < 0 ? reflectance[lm]! * nk[t]! : sk[si]![t]!);\n }\n }\n } else for (let dy = 0, t = 0; dy < ch; dy++) for (let dx = 0; dx < cw; dx++, t++) {\n lattice(g, ti, p0 + dx, q0 + dy);\n let value = 0;\n for (let n = 0; n < nodes; n++) value += weights.perNode[n]![c]![t]! * radiance[n]!;\n sum += lf * value;\n }\n }\n total += sum;\n }\n return total / T;\n }\n const pilotNode = input.wavelengthsNm[Math.floor(nodes / 2)]!;\n if (input.largeKernel) return createLargeLensSignal(input, inFocusLensTile, () => lookups, pilot);\n /** E_c (#564) of the native site positions [x0, x0 + T) × [y0, y0 + T) for the three channels: kernelSite's sum for each channel. */\n function inFocusLensTile(x0: number, y0: number, TS: number): Float64Array[] {\n const out = [0, 1, 2].map(() => new Float64Array(TS * TS));\n // A fixed tile reaches past the raster: positions more than the disc's radius beyond it feed no site, so they stay 0 and are never\n // mapped (the lens profiles are checked only up to the view's reach).\n const D = input.largeKernel!.radius;\n if (x0 + TS <= -D || x0 >= W + D || y0 + TS <= -D || y0 >= H + D) return out;\n if (x0 < -D || x0 + TS > W + D || y0 < -D || y0 + TS > H + D) {\n const xa = Math.max(x0, -D), xb = Math.min(x0 + TS, W + D), ya = Math.max(y0, -D), yb = Math.min(y0 + TS, H + D);\n const part = inFocusLensRect(xa, ya, xb - xa, yb - ya);\n for (let c = 0; c < 3; c++) for (let y = ya; y < yb; y++) out[c]!.set(part[c]!.subarray((y - ya) * (xb - xa), (y - ya + 1) * (xb - xa)), (y - y0) * TS + xa - x0);\n return out;\n }\n return inFocusLensRect(x0, y0, TS, TS);\n }\n /** E_c of the native site positions [x0, x0 + w) × [y0, y0 + h), row-major, for the three channels. */\n function inFocusLensRect(x0: number, y0: number, TW: number, TH: number): Float64Array[] {\n const out = [0, 1, 2].map(() => new Float64Array(TW * TH)), sum = [0, 1, 2].map(() => new Float64Array(TW * TH));\n for (let ti = 0; ti < T; ti++) {\n for (const e of sum) e.fill(0);\n for (const group of groups) {\n const cw = group.cw, ch = group.ch, gw = TW + cw - 1, gh = TH + ch - 1, p0 = x0 + group.minIx - R, q0 = y0 + group.minIy - R;\n const factor = new Float64Array(gw * gh), material = materials ? new Int32Array(gw * gh) : undefined, values = materials ? undefined : new Float64Array(gw * gh * nodes);\n for (let j = 0; j < gh; j++) for (let i = 0; i < gw; i++) {\n const k = j * gw + i;\n map((p0 + i + 0.5 + group.fx - W / 2) * mmPerSite, (q0 + j + 0.5 + group.fy - H / 2) * mmPerSite, times[ti]!);\n factor[k] = pf;\n if (material) material[k] = materialOf(materials!.materialAt(pu, pv));\n else for (let n = 0; n < nodes; n++) values![k * nodes + n] = radianceAt!(pu, pv, input.wavelengthsNm[n]!);\n }\n lookups += material ? gw * gh : gw * gh * nodes;\n for (let c = 0; c < 3; c++) {\n const e = sum[c]!, nk = group.neutral[c], sk = group.spectral[c];\n for (let y = 0; y < TH; y++) for (let x = 0; x < TW; x++) {\n let v = 0;\n for (let dy = 0, t = 0; dy < ch; dy++) for (let dx = 0; dx < cw; dx++, t++) {\n const k = (y + dy) * gw + x + dx;\n if (material) { const m = material[k]!, si = spectralIndex[m]!; v += factor[k]! * (si < 0 ? reflectance[m]! * nk![t]! : sk![si]![t]!); }\n else { let r = 0; for (let n = 0; n < nodes; n++) r += group.perNode[n]![c]![t]! * values![k * nodes + n]!; v += factor[k]! * r; }\n }\n e[y * TW + x] = e[y * TW + x]! + v;\n }\n }\n }\n for (let c = 0; c < 3; c++) { const o = out[c]!, e = sum[c]!; for (let k = 0; k < o.length; k++) o[k] = o[k]! + e[k]!; }\n }\n for (const o of out) for (let k = 0; k < o.length; k++) o[k] = o[k]! / T;\n return out;\n }\n // Site values persist across windows in a ring of native rows (a site's value does not depend on the window).\n let ringRows = 0, ring = new Float64Array(0), ringRowId = new Int32Array(0), ringOn = false;\n const compute = kernels ? kernelSite : directSite;\n return {\n get lookups(): number { return lookups; },\n uniformMaterial: -1,\n tracksMaterial: false,\n get cachesSites(): boolean { return ringOn; },\n marksReads: false,\n markReads(): void { /* never called: marksReads is false */ },\n window(x0: number, y0: number, x1: number, y1: number): void {\n const sw = Math.max(0, x1 - x0), sh = Math.max(0, y1 - y0);\n if (sh > 0 && ringRows < 2 * sh) {\n const rows = pow2(2 * sh);\n if (rows * W <= LATTICE_CACHE_LIMIT) { ringRows = rows; ring = new Float64Array(rows * W).fill(NaN); ringRowId = new Int32Array(rows).fill(-1); }\n }\n ringOn = sh > 0 && ringRows >= 2 * sh;\n if (!kernels || sw === 0) return;\n // The lattice rectangle the window's sites read, per group; the cache keeps two such heights and the columns the render's windows span.\n let cw = 0, ch = 0;\n for (const group of groups) { cw = Math.max(cw, group.cw); ch = Math.max(ch, group.ch); }\n const height = sh + ch - 1, width = sw + cw - 1;\n let rows = pow2(2 * height), cols = pow2(Math.min(W + 2 * (R + cw), Math.max(width, (Number.isFinite(spanColumns) ? spanColumns : W) + width)));\n if (slots * per * rows * cols > LATTICE_CACHE_LIMIT) rows = pow2(height);\n if (slots * per * rows * cols > LATTICE_CACHE_LIMIT) cols = pow2(width);\n if (slots * per * rows * cols > LATTICE_CACHE_LIMIT) { cacheRows = 0; return; }\n if (rows > cacheRows || cols > cacheCols) {\n rows = Math.max(rows, cacheRows); cols = Math.max(cols, cacheCols);\n if (slots * per * rows * cols > LATTICE_CACHE_LIMIT) { rows = pow2(height); cols = pow2(width); }\n cacheRows = rows; cacheCols = cols;\n const size = slots * rows * cols;\n tagQ = new Int32Array(size).fill(-2147483648); tagP = new Int32Array(size); cacheFactor = new Float64Array(size);\n if (materials) cacheMaterial = new Int32Array(size); else cacheRadiance = new Float64Array(size * nodes);\n }\n },\n site(x: number, y: number): number {\n if (!ringOn) return compute(x, y);\n const slot = y & (ringRows - 1), k = slot * W + x;\n if (ringRowId[slot] === y) { const v = ring[k]!; if (v === v) return v; }\n else { ringRowId[slot] = y; ring.fill(NaN, slot * W, (slot + 1) * W); }\n const v = compute(x, y);\n ring[k] = v;\n return v;\n },\n pilot\n };\n /**\n * The renderer's pilot point is a rectilinear plane point of the native raster: back to the sensor point, then through the lens at\n * every temporal midpoint. A point whose scene value differs between the instants (motion) counts as detail (NaN equals nothing).\n */\n function pilot(u: number, v: number): number {\n const g = 2 / input.outputWidth, xMm = u / g * mmPerSite, yMm = -v / g * mmPerSite;\n let first = NaN;\n try {\n for (let ti = 0; ti < T; ti++) {\n map(xMm, yMm, times[ti]!);\n const value = beyond ? -1 : materials ? materials.materialAt(pu, pv) : radianceAt!(pu, pv, pilotNode);\n lookups++;\n if (ti === 0) first = value; else if (value !== first) return NaN;\n }\n } catch { return NaN; }\n return first;\n }\n}\n\n/** #564: tile sides of the large-kernel lens signal (the in-focus E and the convolved sites) and the bytes each tile cache keeps. */\nconst LARGE_E_TILE = 64, LARGE_OUTPUT_TILE = 128, LARGE_CACHE_BYTES = 32 * 1048576;\n\n/** #564: the lens signal with a defocus kernel above 64 sites: D ⊛ E_c by runs over the in-focus tiles (see the module comment). */\nfunction createLargeLensSignal(input: DisplayViewExpectedSignalInput, inFocusTile: (x0: number, y0: number, T: number) => Float64Array[], lookups: () => number,\n pilot: (u: number, v: number) => number): DisplayViewExpectedSignal {\n const runs = input.largeKernel!, channelAt = input.channelAt, TE = LARGE_E_TILE;\n // At least the in-focus tiles one output tile's source spans plus one more row of them, so the next output tile of a row reuses them.\n const span = Math.ceil((LARGE_OUTPUT_TILE + 2 * runs.radius) / TE) + 1;\n const inFocus = new Map<number, Float64Array[]>(), capacity = Math.max(span * (span + 1), Math.floor(LARGE_CACHE_BYTES / (3 * TE * TE * 8)));\n const tileAt = (tx: number, ty: number): Float64Array[] => {\n const key = (ty + 1048576) * 2097152 + tx + 1048576;\n let tile = inFocus.get(key);\n if (tile) { inFocus.delete(key); inFocus.set(key, tile); }\n else {\n tile = inFocusTile(tx * TE, ty * TE, TE);\n inFocus.set(key, tile);\n if (inFocus.size > capacity) inFocus.delete(inFocus.keys().next().value!);\n }\n return tile;\n };\n // Which sites of a tile row hold channel c: the CFA's 2 × 2 period (tile origins are even).\n const phase = [0, 1].map((py) => [0, 1].map((px) => channelAt(px, py)));\n const patterns: SiteKernelRunsRowPattern[] = [0, 1, 2].map((c) => (row: number) => {\n const p = phase[row & 1]!, even = p[0] === c, odd = p[1] === c;\n return even && odd ? { start: 0, step: 1 } : even ? { start: 0, step: 2 } : odd ? { start: 1, step: 2 } : null;\n });\n const lattice = createSiteKernelRunsLattice({ runs, tile: LARGE_OUTPUT_TILE, fields: 3, capacityBytes: LARGE_CACHE_BYTES, pattern: (c) => patterns[c],\n source: (x0, y0, width, height) => (c: number): Float64Array => {\n const samples = new Float64Array(width * height);\n for (let ty = Math.floor(y0 / TE); ty * TE < y0 + height; ty++) for (let tx = Math.floor(x0 / TE); tx * TE < x0 + width; tx++) {\n const tile = tileAt(tx, ty)[c]!, ax = Math.max(x0, tx * TE), bx = Math.min(x0 + width, (tx + 1) * TE), ay = Math.max(y0, ty * TE), by = Math.min(y0 + height, (ty + 1) * TE);\n for (let y = ay; y < by; y++) samples.set(tile.subarray((y - ty * TE) * TE + ax - tx * TE, (y - ty * TE) * TE + bx - tx * TE), (y - y0) * width + ax - x0);\n }\n return samples;\n } });\n return {\n get lookups(): number { return lookups(); },\n uniformMaterial: -1,\n tracksMaterial: false,\n cachesSites: false,\n marksReads: false,\n markReads(): void { /* never called: marksReads is false */ },\n window(): void { /* the tiles are fixed and kept for the signal; a window changes nothing */ },\n site(x: number, y: number): number { return lattice.valueAt(channelAt(x, y), x, y); },\n pilot\n };\n}\n"]}
@@ -69,8 +69,10 @@ export interface DisplayViewSetup {
69
69
  width: number;
70
70
  height: number;
71
71
  };
72
- /** Samples per axis in display pixels whose pilot finds detail; uniform ones use a quarter (at least 1). */
72
+ /** Samples per axis in display pixels whose pilot finds detail. */
73
73
  samplesPerAxis: number;
74
+ /** Samples per axis in uniform ones: a quarter (at least 1), the fast method; `samplesPerAxis` exact (2.20.0). Default a quarter. */
75
+ uniformSamplesPerAxis?: number;
74
76
  /** Sites beyond the footprint that can affect its pixels (demosaic, filter and kernel reach), for the pilot. */
75
77
  reachSites: number;
76
78
  bitDepth: 8 | 16;
@@ -791,7 +791,7 @@ function createGridCorrection(setup, states) {
791
791
  export async function renderDisplayView(setup) {
792
792
  const { frameWidth, frameHeight, margin, nativeWidth, nativeHeight, viewWidth, viewHeight, region, seed, reachSites } = setup;
793
793
  const sx = frameWidth / viewWidth, sy = frameHeight / viewHeight, area = sx * sy, g = 2 / frameWidth;
794
- const fullK = setup.samplesPerAxis, uniformK = Math.max(1, Math.round(fullK / 4));
794
+ const fullK = setup.samplesPerAxis, uniformK = setup.uniformSamplesPerAxis ?? Math.max(1, Math.round(fullK / 4));
795
795
  // Exact area mean (#393): where a footprint holds at most EXACT_AREA_MEAN_MAX_PIXELS real pixels and at most K², every real
796
796
  // pixel it touches is evaluated once with its exact overlap weight a_j = w_j / A, so the expected value is D_P = Σ_j a_j·E[L_j]
797
797
  // with no sampling error at no more cost than sampling; coarser views keep the stratified estimator, whose cost does not