@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":"generic-tier-presets.js","sourceRoot":"","sources":["../../src/equipment/generic-tier-presets.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Generic tier presets: a catalog of exact preset versions for bodies and lenses.\n *\n * There is no hidden \"latest\" alias and no default sensor size. By default the lens tier matches the\n * body tier, but mixing tiers is a normal, supported choice.\n * @see docs/GENERIC_TIER_PRESETS.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { freezeOwnedData } from \"../core/owned-data.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { choice, record, parseOpticalProfileState, type OpticalProfileState, type GenericOpticalEvidence } from \"../optics/profile-contract.js\";\nimport { genericTierAssets, type GenericEquipmentTier, type GenericEquipmentTierPreset, type GenericTierPresetVersion } from \"./generic-tier-assets.js\";\nimport { resolveGenericEquipmentExposureCapabilities } from \"./exposure-capabilities.js\";\nimport { parseGenericLensCorrectionProfile, type GenericLensCorrectionProfile } from \"../output/lens-corrections.js\";\nimport { parseLensStrayLightProfile, type LensStrayLightProfile } from \"../optics/stray-light.js\";\nimport { parseLensComplexPupilProfile, type LensComplexPupilProfile } from \"../optics/complex-pupil-psf.js\";\nimport { parseSceneToSensorIrradianceProfile, type SceneToSensorIrradianceProfile } from \"../optics/scene-to-sensor-irradiance.js\";\nimport type { RadialDistortionProfile } from \"../optics/radial-distortion.js\";\nimport type { LateralChromaticAberrationProfile } from \"../optics/lateral-chromatic-aberration.js\";\nimport type { IlluminationVignettingProfile } from \"../optics/illumination-vignetting.js\";\n\n/** The current preset version (2.14: 2.1.0, third-stop ISO settings). */\nexport const GENERIC_EQUIPMENT_TIER_PRESET_VERSION = \"2.1.0\" as const;\n/** Every exact preset version that resolves, oldest first. A version is never retuned in place (`test/generic-tier-presets.test.ts`). */\nexport const GENERIC_EQUIPMENT_TIER_PRESET_VERSIONS = /* @__PURE__ */ Object.freeze([\"2.0.0\", \"2.1.0\"] as const);\nexport const GENERIC_EQUIPMENT_TIERS = /* @__PURE__ */ Object.freeze([\"consumer\", \"prosumer\", \"professional\"] as const);\nexport interface GenericEquipmentTierProfileReference { profileId: string; profileVersion: string }\nexport interface GenericEquipmentTierSelection {\n schemaVersion: \"0.1.0\"; presetVersion: GenericTierPresetVersion;\n bodyTier: GenericEquipmentTier; lensTier: GenericEquipmentTier;\n bodyPresetId: string; lensPresetId: string;\n profileReferences: readonly GenericEquipmentTierProfileReference[];\n sensorFormatSelectedByTier: false; scientificTierMultiplierApplied: false;\n}\nexport interface ResolvedGenericTierLensProfiles {\n selection: GenericEquipmentTierSelection;\n state: OpticalProfileState;\n radial: RadialDistortionProfile;\n lateralCa: LateralChromaticAberrationProfile;\n vignetting: IlluminationVignettingProfile;\n breathingProjectionScale: number;\n transmission: SceneToSensorIrradianceProfile;\n pupils: readonly LensComplexPupilProfile[];\n stray: LensStrayLightProfile;\n correction: GenericLensCorrectionProfile;\n scientificStatus: \"approximation\";\n}\nconst catalogs = new Map<GenericTierPresetVersion, readonly GenericEquipmentTierPreset[]>();\nfunction catalogOf(version: GenericTierPresetVersion): readonly GenericEquipmentTierPreset[] {\n let catalog = catalogs.get(version);\n if (!catalog) catalogs.set(version, catalog = freezeOwnedData(genericTierAssets(version)));\n return catalog;\n}\nfunction preset(version: GenericTierPresetVersion, tier: GenericEquipmentTier): GenericEquipmentTierPreset {\n return catalogOf(version).find((p) => p.tier === tier)!;\n}\nfunction exactVersion(value: unknown): GenericTierPresetVersion {\n if (!(GENERIC_EQUIPMENT_TIER_PRESET_VERSIONS as readonly unknown[]).includes(value)) {\n throw new InvalidConfigurationError(\"Unknown equipment preset version; historical definitions may not silently fall back.\");\n }\n return value as GenericTierPresetVersion;\n}\n/** Catalog of exact versions. No hidden \"latest\" alias and no default sensor size. */\nexport function resolveGenericEquipmentTierCatalog(input: { presetVersion: string }): readonly GenericEquipmentTierPreset[] {\n const r = record(input, [\"presetVersion\"]);\n return catalogOf(exactVersion(r.presetVersion));\n}\nfunction bodyReferences(p: GenericEquipmentTierPreset): GenericEquipmentTierProfileReference[] {\n const b = p.body;\n return [b.exposure, b.iso, b.signalChain, b.release, b.focus, b.stabilization, b.whiteBalance, b.meteringCapabilities, b.flashSync]\n .map((profile) => ({ profileId: profile.profileId, profileVersion: profile.profileVersion }))\n .concat([...b.readout, b.readoutTiming, b.rollingReadoutTiming, b.fixedPatternNoise, ...b.metering]\n .map((a) => ({ profileId: a.assetId, profileVersion: a.assetVersion })));\n}\n/** The lens tier matches the body tier by default. Mixing tiers is a normal, supported choice. */\nexport function createGenericEquipmentTierSelection(input: {\n presetVersion: string; bodyTier: GenericEquipmentTier; lensTier?: GenericEquipmentTier;\n}): GenericEquipmentTierSelection {\n const r = record(input, [\"presetVersion\", \"bodyTier\", \"lensTier\"]);\n const presetVersion = exactVersion(r.presetVersion);\n const bodyTier = choice(r.bodyTier, GENERIC_EQUIPMENT_TIERS), lensTier = choice(r.lensTier === undefined ? bodyTier : r.lensTier, GENERIC_EQUIPMENT_TIERS);\n const body = preset(presetVersion, bodyTier), lens = preset(presetVersion, lensTier);\n return freezeOwnedData({ schemaVersion: \"0.1.0\", presetVersion, bodyTier, lensTier,\n bodyPresetId: body.presetId+\":body\", lensPresetId: lens.presetId+\":lens\",\n profileReferences: [...bodyReferences(body), { profileId: lens.lens.exposure.profileId, profileVersion: lens.lens.exposure.profileVersion }, ...lens.lens.profileReferences],\n sensorFormatSelectedByTier: false, scientificTierMultiplierApplied: false });\n}\n/** On a saved simulation, rejects profile versions that are stale, missing or retuned, instead of picking today's defaults. */\nexport function parseGenericEquipmentTierSelection(value: unknown): GenericEquipmentTierSelection {\n const r = record(value, [\"schemaVersion\", \"presetVersion\", \"bodyTier\", \"lensTier\", \"bodyPresetId\", \"lensPresetId\", \"profileReferences\",\n \"sensorFormatSelectedByTier\", \"scientificTierMultiplierApplied\"]);\n const expected = createGenericEquipmentTierSelection({ presetVersion: r.presetVersion as string,\n bodyTier: r.bodyTier as GenericEquipmentTier, lensTier: choice(r.lensTier, GENERIC_EQUIPMENT_TIERS) });\n if (r.schemaVersion !== expected.schemaVersion || r.bodyPresetId !== expected.bodyPresetId || r.lensPresetId !== expected.lensPresetId ||\n r.sensorFormatSelectedByTier !== false || r.scientificTierMultiplierApplied !== false || !Array.isArray(r.profileReferences) ||\n r.profileReferences.length !== expected.profileReferences.length) throw new InvalidConfigurationError(\"Saved equipment selection differs from its exact preset manifest.\");\n for (let i = 0; i < expected.profileReferences.length; i++) {\n const ref = record(r.profileReferences[i], [\"profileId\", \"profileVersion\"]), actual = expected.profileReferences[i]!;\n if (ref.profileId !== actual.profileId || ref.profileVersion !== actual.profileVersion) throw new InvalidConfigurationError(\"Saved equipment profile reference drift.\");\n }\n return expected;\n}\n/** Ties the finite matched-reference optical data to one exact generic selected state. Never extrapolates. */\nexport function resolveGenericEquipmentTierLensProfiles(input: { selection: GenericEquipmentTierSelection; state: OpticalProfileState }): ResolvedGenericTierLensProfiles {\n const request = record(input, [\"selection\", \"state\"]), selection = parseGenericEquipmentTierSelection(request.selection), state = parseOpticalProfileState(request.state);\n const b = preset(selection.presetVersion, selection.bodyTier), l = preset(selection.presetVersion, selection.lensTier), a = l.lens.matchedReference;\n if (state.bodyId !== b.body.exposure.profileId.replace(/:exposure$/, \"\") || state.bodyVersion !== selection.presetVersion ||\n state.lensId !== l.lens.exposure.profileId.replace(/:exposure$/, \"\") || state.lensVersion !== selection.presetVersion ||\n state.focalLengthMm !== a.focalLengthMm || state.aperture !== a.aperture || state.focusDistanceM !== a.focusDistanceM ||\n state.captureMode !== \"still\" || state.stabilizationMode !== \"off\") throw new InvalidConfigurationError(\"No optical reference slice for this exact generic system/acquisition state.\");\n resolveGenericEquipmentExposureCapabilities({ bodyProfile: b.body.exposure, lensProfile: l.lens.exposure, selectedFocalLengthMm: state.focalLengthMm });\n const id = state.lensId, version = state.lensVersion, evidence = l.evidence;\n const opticalEvidence: GenericOpticalEvidence = { kind: \"generic-parametric\", basis: \"Photivra-owned educational tier design values, not measured calibration.\",\n residualNote: \"Finite matched-reference approximation; no branded signature or aggregate physical error bound.\", sources: evidence };\n const coeff = (k1: number): RadialDistortionProfile => ({ normalizationRadiusMm: a.normalizationRadiusMm, maximumNormalizedRadius: 1.1,\n coefficients: { k1, k2: 0, k3: 0 } });\n const radial = coeff(a.distortionK1), lateralCa: LateralChromaticAberrationProfile = { normalizationRadiusMm: a.normalizationRadiusMm,\n maximumNormalizedRadius: 1.1, baseDistortionCoefficients: radial.coefficients,\n redCoefficientOffset: { k1: a.lateralCaK1Offset, k2: 0, k3: 0 }, blueCoefficientOffset: { k1: -a.lateralCaK1Offset, k2: 0, k3: 0 } };\n const vignetting: IlluminationVignettingProfile = { normalizationRadiusMm: a.normalizationRadiusMm, maximumNormalizedRadius: 1.1,\n coefficients: { r2: a.vignettingR2, r4: 0, r6: 0 } };\n const identity = { version, domain: \"reconstructed-linear\" as const, availability: \"toggle\" as const, defaultEnabled: true,\n dependencies: [], requiredByStabilizationModes: [], residualNote: opticalEvidence.residualNote };\n const correction = parseGenericLensCorrectionProfile({ schemaVersion: \"0.1.0\", id: id+\":correction\", version, state, evidence: opticalEvidence,\n components: [{ ...identity, id: \"geometry\", kind: \"geometry\", transform: { id: id+\":radial-map\", version,\n domain: \"reconstructed-linear\", purpose: \"distortion\", kind: \"radial\", profile: radial } },\n { ...identity, id: \"lateral-ca\", kind: \"lateral-ca\", transforms: Object.fromEntries([\"red\", \"green\", \"blue\"].map((channel, i) => [channel, {\n id: id+\":ca-map:\"+channel, version, domain: \"reconstructed-linear\", purpose: \"lateral-ca\", kind: \"radial\",\n profile: coeff([a.lateralCaK1Offset*a.correctionCaFraction, 0, -a.lateralCaK1Offset*a.correctionCaFraction][i]!) }])) },\n { ...identity, id: \"gain\", kind: \"peripheral-illumination\", profile: vignetting, strength: a.correctionGainStrength }] });\n const stray = parseLensStrayLightProfile({ schemaVersion: \"0.1.0\", id: id+\":stray\", version, state, evidence: opticalEvidence,\n interaction: \"lens-reflections\", wavelengthNm: a.wavelengthNm, wavelengthBasis: \"vacuum\", maximumSourceAngleDegrees: 60,\n referenceEntranceAreaMm2: Math.PI*(50/4/2)**2, responses: [\n { id: \"ghost\", kind: \"ghost\", centroidMmPerDegree: [-.02,0,0,-.02], offsetMm: { x: 1, y: 0 }, sigmaMm: .5, axisPowerFraction: a.ghostPowerFraction, angularSlope: 1 },\n { id: \"veil\", kind: \"veil\", centroidMmPerDegree: [0,0,0,0], offsetMm: { x: 0, y: 0 }, sigmaMm: 10, axisPowerFraction: a.veilPowerFraction, angularSlope: 0 }] });\n const transmission = parseSceneToSensorIrradianceProfile({ schemaVersion: \"0.1.0\", profileId: id+\":transmission\", profileVersion: version, lensProfileId: id,\n scientificStatus: \"approximation\", applicability: { focalLengthMm: { minimum: 50, maximum: 50 }, nominalFNumber: { minimum: 4, maximum: 4 },\n focus: { kind: \"finite-distance-range\", objectDistanceM: { minimum: 5, maximum: 5 } } }, transmission: { kind: \"spectral-transmission\", scientificStatus: \"approximation\",\n wavelengthBasis: \"vacuum\", samples: { value: [{ wavelengthNanometers: 380, linearTransmissionFactor: a.transmission },\n { wavelengthNanometers: 780, linearTransmissionFactor: a.transmission }], evidence }, uncertainty: { kind: \"not-quantified\", limitation: \"Synthetic spectrally flat reference over 380-780 nm.\" } },\n distortionAreaMappingOwnership: \"not-applied-by-bridge\", psfRedistributionOwnership: \"downstream-normalized-energy-redistribution\", sensorOpticalStackIncluded: false,\n strayLightIncluded: false, polarizationModeled: false, wavelengthChangingBehaviorModeled: false, volumetricScatteringModeled: false, evidence, limitations: l.lens.limitations });\n const pupils = [0,1,2].flatMap((field) => [-20,0,20].map((defocus, index) => parseLensComplexPupilProfile({ schemaVersion: \"0.1.0\",\n profileId: id+\":pupil:\"+field+\":\"+index, profileVersion: version, scientificStatus: \"approximation\", opticalDomain: \"lens-primary-optical-path-only\",\n representation: \"complex-pupil-amplitude-plus-opd\", pupilCoordinateSystem: \"pupil-plane-metric-aligned-to-image-plane\", imageFieldAxes: \"+X right, +Y up\",\n amplitudeMeaning: \"relative-complex-pupil-amplitude-shape\", wavefrontMeaning: \"optical-path-difference-micrometers\",\n throughputOwnership: \"separate-relative-pupil-throughput-factor\", kernelEnergyNormalization: \"unit-energy-shape\", propagationModel: \"scalar-fraunhofer-discrete-reference\",\n context: { focalLengthMm: 50, focus: { kind: \"finite\", distanceM: 5 }, apertureFNumber: 4, fieldPointMm: [{x:0,y:0},{x:10,y:6},{x:18,y:12}][field],\n wavelengthNm: 550, signedDefocusImagePlaneMicrometers: defocus }, responseIncludes: { diffraction: true, aberration: true, defocus: true, pupilClippingShape: true },\n relativePupilThroughputFactor: a.pupilThroughputByField[field], grid: { widthSamples: 5, heightSamples: 5, pupilSamplePitchMmX: 3.125, pupilSamplePitchMmY: 3.125,\n centerSampleX: 2, centerSampleY: 2, relativeAmplitude: a.pupilAmplitudeByField[field], opticalPathDifferenceMicrometers: a.pupilOpdMicrometersByDefocus[index] },\n sensorOpticalStackIncluded: false, sensorSamplingIncluded: false, reconstructionIncluded: false, strayLightIncluded: false, evidence,\n uncertainty: { kind: \"not-quantified\", limitation: \"Coarse independently designed pupil-grid reference only.\" }, limitations: l.lens.limitations })));\n return freezeOwnedData({ selection, state, radial, lateralCa, vignetting, breathingProjectionScale: a.breathingProjectionScale, transmission, pupils, stray, correction,\n scientificStatus: \"approximation\" });\n}\n"]}
1
+ {"version":3,"file":"generic-tier-presets.js","sourceRoot":"","sources":["../../src/equipment/generic-tier-presets.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Generic tier presets: a catalog of exact preset versions for bodies and lenses.\n *\n * There is no hidden \"latest\" alias and no default sensor size. By default the lens tier matches the\n * body tier, but mixing tiers is a normal, supported choice.\n * @see docs/GENERIC_TIER_PRESETS.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { freezeOwnedData } from \"../core/owned-data.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { choice, record, parseOpticalProfileState, type OpticalProfileState, type GenericOpticalEvidence } from \"../optics/profile-contract.js\";\nimport { genericTierAssets, type GenericEquipmentTier, type GenericEquipmentTierPreset, type GenericTierPresetVersion } from \"./generic-tier-assets.js\";\nimport { resolveGenericEquipmentExposureCapabilities } from \"./exposure-capabilities.js\";\nimport { parseGenericLensCorrectionProfile, type GenericLensCorrectionProfile } from \"../output/lens-corrections.js\";\nimport { parseLensStrayLightProfile, type LensStrayLightProfile } from \"../optics/stray-light.js\";\nimport { parseLensComplexPupilProfile, type LensComplexPupilProfile } from \"../optics/complex-pupil-psf.js\";\nimport { parseSceneToSensorIrradianceProfile, SCENE_TO_SENSOR_BRIDGE_SCOPE, type SceneToSensorIrradianceProfile } from \"../optics/scene-to-sensor-irradiance.js\";\nimport type { RadialDistortionProfile } from \"../optics/radial-distortion.js\";\nimport type { LateralChromaticAberrationProfile } from \"../optics/lateral-chromatic-aberration.js\";\nimport type { IlluminationVignettingProfile } from \"../optics/illumination-vignetting.js\";\n\n/** The current preset version (2.14: 2.1.0, third-stop ISO settings). */\nexport const GENERIC_EQUIPMENT_TIER_PRESET_VERSION = \"2.1.0\" as const;\n/** Every exact preset version that resolves, oldest first. A version is never retuned in place (`test/generic-tier-presets.test.ts`). */\nexport const GENERIC_EQUIPMENT_TIER_PRESET_VERSIONS = /* @__PURE__ */ Object.freeze([\"2.0.0\", \"2.1.0\"] as const);\nexport const GENERIC_EQUIPMENT_TIERS = /* @__PURE__ */ Object.freeze([\"consumer\", \"prosumer\", \"professional\"] as const);\nexport interface GenericEquipmentTierProfileReference { profileId: string; profileVersion: string }\nexport interface GenericEquipmentTierSelection {\n schemaVersion: \"0.1.0\"; presetVersion: GenericTierPresetVersion;\n bodyTier: GenericEquipmentTier; lensTier: GenericEquipmentTier;\n bodyPresetId: string; lensPresetId: string;\n profileReferences: readonly GenericEquipmentTierProfileReference[];\n sensorFormatSelectedByTier: false; scientificTierMultiplierApplied: false;\n}\nexport interface ResolvedGenericTierLensProfiles {\n selection: GenericEquipmentTierSelection;\n state: OpticalProfileState;\n radial: RadialDistortionProfile;\n lateralCa: LateralChromaticAberrationProfile;\n vignetting: IlluminationVignettingProfile;\n breathingProjectionScale: number;\n transmission: SceneToSensorIrradianceProfile;\n pupils: readonly LensComplexPupilProfile[];\n stray: LensStrayLightProfile;\n correction: GenericLensCorrectionProfile;\n scientificStatus: \"approximation\";\n}\nconst catalogs = new Map<GenericTierPresetVersion, readonly GenericEquipmentTierPreset[]>();\nfunction catalogOf(version: GenericTierPresetVersion): readonly GenericEquipmentTierPreset[] {\n let catalog = catalogs.get(version);\n if (!catalog) catalogs.set(version, catalog = freezeOwnedData(genericTierAssets(version)));\n return catalog;\n}\nfunction preset(version: GenericTierPresetVersion, tier: GenericEquipmentTier): GenericEquipmentTierPreset {\n return catalogOf(version).find((p) => p.tier === tier)!;\n}\nfunction exactVersion(value: unknown): GenericTierPresetVersion {\n if (!(GENERIC_EQUIPMENT_TIER_PRESET_VERSIONS as readonly unknown[]).includes(value)) {\n throw new InvalidConfigurationError(\"Unknown equipment preset version; historical definitions may not silently fall back.\");\n }\n return value as GenericTierPresetVersion;\n}\n/** Catalog of exact versions. No hidden \"latest\" alias and no default sensor size. */\nexport function resolveGenericEquipmentTierCatalog(input: { presetVersion: string }): readonly GenericEquipmentTierPreset[] {\n const r = record(input, [\"presetVersion\"]);\n return catalogOf(exactVersion(r.presetVersion));\n}\nfunction bodyReferences(p: GenericEquipmentTierPreset): GenericEquipmentTierProfileReference[] {\n const b = p.body;\n return [b.exposure, b.iso, b.signalChain, b.release, b.focus, b.stabilization, b.whiteBalance, b.meteringCapabilities, b.flashSync]\n .map((profile) => ({ profileId: profile.profileId, profileVersion: profile.profileVersion }))\n .concat([...b.readout, b.readoutTiming, b.rollingReadoutTiming, b.fixedPatternNoise, ...b.metering]\n .map((a) => ({ profileId: a.assetId, profileVersion: a.assetVersion })));\n}\n/** The lens tier matches the body tier by default. Mixing tiers is a normal, supported choice. */\nexport function createGenericEquipmentTierSelection(input: {\n presetVersion: string; bodyTier: GenericEquipmentTier; lensTier?: GenericEquipmentTier;\n}): GenericEquipmentTierSelection {\n const r = record(input, [\"presetVersion\", \"bodyTier\", \"lensTier\"]);\n const presetVersion = exactVersion(r.presetVersion);\n const bodyTier = choice(r.bodyTier, GENERIC_EQUIPMENT_TIERS), lensTier = choice(r.lensTier === undefined ? bodyTier : r.lensTier, GENERIC_EQUIPMENT_TIERS);\n const body = preset(presetVersion, bodyTier), lens = preset(presetVersion, lensTier);\n return freezeOwnedData({ schemaVersion: \"0.1.0\", presetVersion, bodyTier, lensTier,\n bodyPresetId: body.presetId+\":body\", lensPresetId: lens.presetId+\":lens\",\n profileReferences: [...bodyReferences(body), { profileId: lens.lens.exposure.profileId, profileVersion: lens.lens.exposure.profileVersion }, ...lens.lens.profileReferences],\n sensorFormatSelectedByTier: false, scientificTierMultiplierApplied: false });\n}\n/** On a saved simulation, rejects profile versions that are stale, missing or retuned, instead of picking today's defaults. */\nexport function parseGenericEquipmentTierSelection(value: unknown): GenericEquipmentTierSelection {\n const r = record(value, [\"schemaVersion\", \"presetVersion\", \"bodyTier\", \"lensTier\", \"bodyPresetId\", \"lensPresetId\", \"profileReferences\",\n \"sensorFormatSelectedByTier\", \"scientificTierMultiplierApplied\"]);\n const expected = createGenericEquipmentTierSelection({ presetVersion: r.presetVersion as string,\n bodyTier: r.bodyTier as GenericEquipmentTier, lensTier: choice(r.lensTier, GENERIC_EQUIPMENT_TIERS) });\n if (r.schemaVersion !== expected.schemaVersion || r.bodyPresetId !== expected.bodyPresetId || r.lensPresetId !== expected.lensPresetId ||\n r.sensorFormatSelectedByTier !== false || r.scientificTierMultiplierApplied !== false || !Array.isArray(r.profileReferences) ||\n r.profileReferences.length !== expected.profileReferences.length) throw new InvalidConfigurationError(\"Saved equipment selection differs from its exact preset manifest.\");\n for (let i = 0; i < expected.profileReferences.length; i++) {\n const ref = record(r.profileReferences[i], [\"profileId\", \"profileVersion\"]), actual = expected.profileReferences[i]!;\n if (ref.profileId !== actual.profileId || ref.profileVersion !== actual.profileVersion) throw new InvalidConfigurationError(\"Saved equipment profile reference drift.\");\n }\n return expected;\n}\n/** Ties the finite matched-reference optical data to one exact generic selected state. Never extrapolates. */\nexport function resolveGenericEquipmentTierLensProfiles(input: { selection: GenericEquipmentTierSelection; state: OpticalProfileState }): ResolvedGenericTierLensProfiles {\n const request = record(input, [\"selection\", \"state\"]), selection = parseGenericEquipmentTierSelection(request.selection), state = parseOpticalProfileState(request.state);\n const b = preset(selection.presetVersion, selection.bodyTier), l = preset(selection.presetVersion, selection.lensTier), a = l.lens.matchedReference;\n if (state.bodyId !== b.body.exposure.profileId.replace(/:exposure$/, \"\") || state.bodyVersion !== selection.presetVersion ||\n state.lensId !== l.lens.exposure.profileId.replace(/:exposure$/, \"\") || state.lensVersion !== selection.presetVersion ||\n state.focalLengthMm !== a.focalLengthMm || state.aperture !== a.aperture || state.focusDistanceM !== a.focusDistanceM ||\n state.captureMode !== \"still\" || state.stabilizationMode !== \"off\") throw new InvalidConfigurationError(\"No optical reference slice for this exact generic system/acquisition state.\");\n resolveGenericEquipmentExposureCapabilities({ bodyProfile: b.body.exposure, lensProfile: l.lens.exposure, selectedFocalLengthMm: state.focalLengthMm });\n const id = state.lensId, version = state.lensVersion, evidence = l.evidence;\n const opticalEvidence: GenericOpticalEvidence = { kind: \"generic-parametric\", basis: \"Photivra-owned educational tier design values, not measured calibration.\",\n residualNote: \"Finite matched-reference approximation; no branded signature or aggregate physical error bound.\", sources: evidence };\n const coeff = (k1: number): RadialDistortionProfile => ({ normalizationRadiusMm: a.normalizationRadiusMm, maximumNormalizedRadius: 1.1,\n coefficients: { k1, k2: 0, k3: 0 } });\n const radial = coeff(a.distortionK1), lateralCa: LateralChromaticAberrationProfile = { normalizationRadiusMm: a.normalizationRadiusMm,\n maximumNormalizedRadius: 1.1, baseDistortionCoefficients: radial.coefficients,\n redCoefficientOffset: { k1: a.lateralCaK1Offset, k2: 0, k3: 0 }, blueCoefficientOffset: { k1: -a.lateralCaK1Offset, k2: 0, k3: 0 } };\n const vignetting: IlluminationVignettingProfile = { normalizationRadiusMm: a.normalizationRadiusMm, maximumNormalizedRadius: 1.1,\n coefficients: { r2: a.vignettingR2, r4: 0, r6: 0 } };\n const identity = { version, domain: \"reconstructed-linear\" as const, availability: \"toggle\" as const, defaultEnabled: true,\n dependencies: [], requiredByStabilizationModes: [], residualNote: opticalEvidence.residualNote };\n const correction = parseGenericLensCorrectionProfile({ schemaVersion: \"0.1.0\", id: id+\":correction\", version, state, evidence: opticalEvidence,\n components: [{ ...identity, id: \"geometry\", kind: \"geometry\", transform: { id: id+\":radial-map\", version,\n domain: \"reconstructed-linear\", purpose: \"distortion\", kind: \"radial\", profile: radial } },\n { ...identity, id: \"lateral-ca\", kind: \"lateral-ca\", transforms: Object.fromEntries([\"red\", \"green\", \"blue\"].map((channel, i) => [channel, {\n id: id+\":ca-map:\"+channel, version, domain: \"reconstructed-linear\", purpose: \"lateral-ca\", kind: \"radial\",\n profile: coeff([a.lateralCaK1Offset*a.correctionCaFraction, 0, -a.lateralCaK1Offset*a.correctionCaFraction][i]!) }])) },\n { ...identity, id: \"gain\", kind: \"peripheral-illumination\", profile: vignetting, strength: a.correctionGainStrength }] });\n const stray = parseLensStrayLightProfile({ schemaVersion: \"0.1.0\", id: id+\":stray\", version, state, evidence: opticalEvidence,\n interaction: \"lens-reflections\", wavelengthNm: a.wavelengthNm, wavelengthBasis: \"vacuum\", maximumSourceAngleDegrees: 60,\n referenceEntranceAreaMm2: Math.PI*(50/4/2)**2, responses: [\n { id: \"ghost\", kind: \"ghost\", centroidMmPerDegree: [-.02,0,0,-.02], offsetMm: { x: 1, y: 0 }, sigmaMm: .5, axisPowerFraction: a.ghostPowerFraction, angularSlope: 1 },\n { id: \"veil\", kind: \"veil\", centroidMmPerDegree: [0,0,0,0], offsetMm: { x: 0, y: 0 }, sigmaMm: 10, axisPowerFraction: a.veilPowerFraction, angularSlope: 0 }] });\n const transmission = parseSceneToSensorIrradianceProfile({ schemaVersion: \"0.1.0\", profileId: id+\":transmission\", profileVersion: version, lensProfileId: id,\n scientificStatus: \"approximation\", applicability: { focalLengthMm: { minimum: 50, maximum: 50 }, nominalFNumber: { minimum: 4, maximum: 4 },\n focus: { kind: \"finite-distance-range\", objectDistanceM: { minimum: 5, maximum: 5 } } }, transmission: { kind: \"spectral-transmission\", scientificStatus: \"approximation\",\n wavelengthBasis: \"vacuum\", samples: { value: [{ wavelengthNanometers: 380, linearTransmissionFactor: a.transmission },\n { wavelengthNanometers: 780, linearTransmissionFactor: a.transmission }], evidence }, uncertainty: { kind: \"not-quantified\", limitation: \"Synthetic spectrally flat reference over 380-780 nm.\" } },\n ...SCENE_TO_SENSOR_BRIDGE_SCOPE, evidence, limitations: l.lens.limitations });\n const pupils = [0,1,2].flatMap((field) => [-20,0,20].map((defocus, index) => parseLensComplexPupilProfile({ schemaVersion: \"0.1.0\",\n profileId: id+\":pupil:\"+field+\":\"+index, profileVersion: version, scientificStatus: \"approximation\", opticalDomain: \"lens-primary-optical-path-only\",\n representation: \"complex-pupil-amplitude-plus-opd\", pupilCoordinateSystem: \"pupil-plane-metric-aligned-to-image-plane\", imageFieldAxes: \"+X right, +Y up\",\n amplitudeMeaning: \"relative-complex-pupil-amplitude-shape\", wavefrontMeaning: \"optical-path-difference-micrometers\",\n throughputOwnership: \"separate-relative-pupil-throughput-factor\", kernelEnergyNormalization: \"unit-energy-shape\", propagationModel: \"scalar-fraunhofer-discrete-reference\",\n context: { focalLengthMm: 50, focus: { kind: \"finite\", distanceM: 5 }, apertureFNumber: 4, fieldPointMm: [{x:0,y:0},{x:10,y:6},{x:18,y:12}][field],\n wavelengthNm: 550, signedDefocusImagePlaneMicrometers: defocus }, responseIncludes: { diffraction: true, aberration: true, defocus: true, pupilClippingShape: true },\n relativePupilThroughputFactor: a.pupilThroughputByField[field], grid: { widthSamples: 5, heightSamples: 5, pupilSamplePitchMmX: 3.125, pupilSamplePitchMmY: 3.125,\n centerSampleX: 2, centerSampleY: 2, relativeAmplitude: a.pupilAmplitudeByField[field], opticalPathDifferenceMicrometers: a.pupilOpdMicrometersByDefocus[index] },\n sensorOpticalStackIncluded: false, sensorSamplingIncluded: false, reconstructionIncluded: false, strayLightIncluded: false, evidence,\n uncertainty: { kind: \"not-quantified\", limitation: \"Coarse independently designed pupil-grid reference only.\" }, limitations: l.lens.limitations })));\n return freezeOwnedData({ selection, state, radial, lateralCa, vignetting, breathingProjectionScale: a.breathingProjectionScale, transmission, pupils, stray, correction,\n scientificStatus: \"approximation\" });\n}\n"]}
@@ -15,48 +15,9 @@
15
15
  import { InvalidConfigurationError } from "../core/configuration-error.js";
16
16
  import { parseEvidenceList } from "../core/evidence-provenance.js";
17
17
  import { InvalidScientificInputError } from "../core/validation.js";
18
- import { requireInputKeys, rejectUnknownFields, rejectUnknownVariantFields } from "../core/record-validation.js";
18
+ import { requireInputKeys, rejectUnknownVariantFields, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, requireConfigPositiveFinite as requirePositiveFinite, parseConfigAvailability as parseAvailability } from "../core/record-validation.js";
19
+ import { parseRange } from "./exposure-capabilities.js";
19
20
  export const ISO_CAPABILITY_PROFILE_SCHEMA_VERSION = "0.1.0";
20
- function requireRecord(value, path, allowedKeys) {
21
- if (typeof value !== "object" ||
22
- value === null ||
23
- Array.isArray(value)) {
24
- throw new InvalidConfigurationError(path + " must be an object.");
25
- }
26
- if (allowedKeys !== null)
27
- rejectUnknownFields(value, allowedKeys, path);
28
- return value;
29
- }
30
- function requireNonEmptyString(value, path) {
31
- if (typeof value !== "string" ||
32
- value.trim().length === 0) {
33
- throw new InvalidConfigurationError(path +
34
- " must be a non-empty string.");
35
- }
36
- return value.trim();
37
- }
38
- function requirePositiveFinite(value, path) {
39
- if (typeof value !== "number" ||
40
- !Number.isFinite(value) ||
41
- value <= 0) {
42
- throw new InvalidConfigurationError(path +
43
- " must be finite and greater than zero.");
44
- }
45
- return value;
46
- }
47
- function parseRange(value, path) {
48
- const record = requireRecord(value, path, ["minimum", "maximum"]);
49
- const minimum = requirePositiveFinite(record.minimum, path + ".minimum");
50
- const maximum = requirePositiveFinite(record.maximum, path + ".maximum");
51
- if (minimum > maximum) {
52
- throw new InvalidConfigurationError(path +
53
- ".minimum must be less than or equal to maximum.");
54
- }
55
- return {
56
- minimum,
57
- maximum
58
- };
59
- }
60
21
  function rangeWithin(inner, outer) {
61
22
  return (inner.minimum >=
62
23
  outer.minimum &&
@@ -112,14 +73,6 @@ function parseGrid(value, range, path) {
112
73
  }
113
74
  throw new InvalidConfigurationError(path + ".kind is invalid.");
114
75
  }
115
- function parseAvailability(value, path) {
116
- if (value !== "supported" &&
117
- value !== "unsupported" &&
118
- value !== "unknown") {
119
- throw new InvalidConfigurationError(path + " is invalid.");
120
- }
121
- return value;
122
- }
123
76
  function parseAutoIso(value, standardRange, path) {
124
77
  const record = requireRecord(value, path, ["availability", "evidence", "standardExposureIndexRange"]);
125
78
  const availability = parseAvailability(record.availability, path + ".availability");
@@ -1 +1 @@
1
- {"version":3,"file":"iso-capabilities.js","sourceRoot":"","sources":["../../src/equipment/iso-capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * ISO capabilities: which standard, expanded and Auto ISO settings a body offers, and in which\n * capture modes.\n *\n * The parser validates untrusted input and returns the normalized typed contract. Unknown enum\n * values, missing required fields and incompatible scientific data are rejected.\n *\n * ISO is an exposure-index (EI) control setting. It does not create photons and says nothing about\n * read noise. Standard and expanded settings, limits per capture mode, and whether Auto ISO is\n * available are all stated explicitly. If availability is unknown, automatic control is not allowed.\n * @see docs/GENERIC_TIER_PRESETS.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport type {\n ResolvedGenericEquipmentExposureCapabilities,\n ResolvedNumericSettingGrid\n} from \"./exposure-capabilities.js\";\nimport { requireInputKeys, rejectUnknownFields, rejectUnknownVariantFields } from \"../core/record-validation.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport const ISO_CAPABILITY_PROFILE_SCHEMA_VERSION =\n \"0.1.0\" as const;\n\nexport type IsoCapabilityAvailability =\n | \"supported\"\n | \"unsupported\"\n | \"unknown\";\n\nexport interface IsoExposureIndexRange {\n minimum: number;\n maximum: number;\n}\n\nexport type IsoStandardSettingGrid =\n | {\n kind: \"continuous-within-range\";\n }\n | {\n kind: \"discrete-values\";\n values: readonly number[];\n };\n\nexport interface IsoExpandedSetting {\n settingId: string;\n label: string;\n direction: \"low\" | \"high\";\n exposureIndexEquivalent: number;\n autoIsoEligible: boolean;\n evidence: readonly EvidenceProvenance[];\n}\n\nexport type IsoAutoIsoCapability =\n | {\n availability: \"supported\";\n standardExposureIndexRange:\n IsoExposureIndexRange;\n evidence: readonly EvidenceProvenance[];\n }\n | {\n availability:\n | \"unsupported\"\n | \"unknown\";\n evidence: readonly EvidenceProvenance[];\n };\n\nexport interface IsoCaptureModePolicy {\n captureModeId: string;\n standardExposureIndexRange:\n IsoExposureIndexRange;\n expandedSettingIds:\n readonly string[];\n autoIso:\n IsoAutoIsoCapability;\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface IsoCapabilityProfile {\n schemaVersion:\n typeof ISO_CAPABILITY_PROFILE_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n capabilityMeaning:\n \"reported-exposure-index-capability-not-physical-gain\";\n standard: {\n exposureIndexRange:\n IsoExposureIndexRange;\n settingGrid:\n IsoStandardSettingGrid;\n };\n expandedSettings:\n readonly IsoExpandedSetting[];\n autoIso:\n IsoAutoIsoCapability;\n captureModePolicies:\n readonly IsoCaptureModePolicy[];\n evidence:\n readonly EvidenceProvenance[];\n}\n\nexport type RequestedIsoSetting =\n | {\n kind: \"standard\";\n exposureIndex: number;\n }\n | {\n kind: \"expanded\";\n settingId: string;\n };\n\nexport interface ResolveIsoCapabilityInput {\n profile:\n IsoCapabilityProfile;\n setting:\n RequestedIsoSetting;\n captureModeId?: string;\n}\n\nexport interface ResolvedIsoCapability {\n profileId: string;\n profileVersion: string;\n captureModeId: string | null;\n setting:\n | {\n kind: \"standard\";\n exposureIndex: number;\n }\n | {\n kind: \"expanded\";\n settingId: string;\n label: string;\n direction:\n \"low\" | \"high\";\n exposureIndexEquivalent:\n number;\n };\n reportedExposureIndex: number;\n expandedSetting: boolean;\n autoIsoEligible:\n boolean;\n standardExposureIndexRange:\n IsoExposureIndexRange;\n standardSettingGrid:\n IsoStandardSettingGrid;\n autoIso:\n IsoAutoIsoCapability;\n capturedPhotonExpectationModified:\n false;\n photonShotNoiseStatisticsModified:\n false;\n physicalGainInferred:\n false;\n conversionGainInferred:\n false;\n readNoiseInferred: false;\n saturationInferred: false;\n exactCommercialCameraBehaviorClaimed:\n false;\n}\n\nfunction requireRecord(\n value: unknown,\n path: string,\n allowedKeys: readonly string[] | null\n): UnknownRecord {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be an object.\"\n );\n }\n if (allowedKeys !== null) rejectUnknownFields(value, allowedKeys, path);\n return value as UnknownRecord;\n}\n\nfunction requireNonEmptyString(\n value: unknown,\n path: string\n): string {\n if (\n typeof value !== \"string\" ||\n value.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must be a non-empty string.\"\n );\n }\n return value.trim();\n}\n\nfunction requirePositiveFinite(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n value <= 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must be finite and greater than zero.\"\n );\n }\n return value;\n}\n\nfunction parseRange(\n value: unknown,\n path: string\n): IsoExposureIndexRange {\n const record =\n requireRecord(value, path, [\"minimum\", \"maximum\"]);\n const minimum =\n requirePositiveFinite(\n record.minimum,\n path + \".minimum\"\n );\n const maximum =\n requirePositiveFinite(\n record.maximum,\n path + \".maximum\"\n );\n if (minimum > maximum) {\n throw new InvalidConfigurationError(\n path +\n \".minimum must be less than or equal to maximum.\"\n );\n }\n return {\n minimum,\n maximum\n };\n}\n\nfunction rangeWithin(\n inner:\n IsoExposureIndexRange,\n outer:\n IsoExposureIndexRange\n): boolean {\n return (\n inner.minimum >=\n outer.minimum &&\n inner.maximum <=\n outer.maximum\n );\n}\n\nfunction parseGrid(\n value: unknown,\n range:\n IsoExposureIndexRange,\n path: string\n): IsoStandardSettingGrid {\n const record =\n requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", { \"continuous-within-range\": [\"kind\"], \"discrete-values\": [\"kind\", \"values\"] }, path);\n if (\n record.kind ===\n \"continuous-within-range\"\n ) {\n return {\n kind:\n \"continuous-within-range\"\n };\n }\n if (\n record.kind ===\n \"discrete-values\"\n ) {\n if (\n !Array.isArray(\n record.values\n ) ||\n record.values.length === 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must be a non-empty array.\"\n );\n }\n let previous =\n Number.NEGATIVE_INFINITY;\n const values =\n record.values.map(\n (entry, index) => {\n const parsed =\n requirePositiveFinite(\n entry,\n path +\n \".values[\" +\n index +\n \"]\"\n );\n if (\n parsed <= previous\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must be strictly increasing.\"\n );\n }\n if (\n parsed <\n range.minimum ||\n parsed >\n range.maximum\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must remain inside the standard ISO range.\"\n );\n }\n previous = parsed;\n return parsed;\n }\n );\n if (\n values[0] !==\n range.minimum ||\n values[\n values.length - 1\n ] !== range.maximum\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must include the exact standard range endpoints.\"\n );\n }\n return {\n kind:\n \"discrete-values\",\n values\n };\n }\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseAvailability(\n value: unknown,\n path: string\n): IsoCapabilityAvailability {\n if (\n value !== \"supported\" &&\n value !== \"unsupported\" &&\n value !== \"unknown\"\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value;\n}\n\nfunction parseAutoIso(\n value: unknown,\n standardRange:\n IsoExposureIndexRange,\n path: string\n): IsoAutoIsoCapability {\n const record =\n requireRecord(value, path, [\"availability\", \"evidence\", \"standardExposureIndexRange\"]);\n const availability =\n parseAvailability(\n record.availability,\n path + \".availability\"\n );\n const evidence =\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n );\n\n if (\n availability ===\n \"supported\"\n ) {\n const autoRange =\n parseRange(\n record\n .standardExposureIndexRange,\n path +\n \".standardExposureIndexRange\"\n );\n if (\n !rangeWithin(\n autoRange,\n standardRange\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".standardExposureIndexRange must lie inside the standard ISO range.\"\n );\n }\n return {\n availability:\n \"supported\",\n standardExposureIndexRange:\n autoRange,\n evidence\n };\n }\n\n if (\n record\n .standardExposureIndexRange !==\n undefined\n ) {\n throw new InvalidConfigurationError(\n path +\n \".standardExposureIndexRange must be omitted unless Auto ISO is supported.\"\n );\n }\n\n return {\n availability,\n evidence\n };\n}\n\nfunction parseExpandedSetting(\n value: unknown,\n standardRange:\n IsoExposureIndexRange,\n path: string\n): IsoExpandedSetting {\n const record =\n requireRecord(value, path, [\"direction\", \"exposureIndexEquivalent\", \"autoIsoEligible\", \"settingId\", \"label\", \"evidence\"]);\n const direction =\n record.direction;\n if (\n direction !== \"low\" &&\n direction !== \"high\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \".direction must be low or high.\"\n );\n }\n const exposureIndexEquivalent =\n requirePositiveFinite(\n record\n .exposureIndexEquivalent,\n path +\n \".exposureIndexEquivalent\"\n );\n if (\n (\n direction === \"low\" &&\n exposureIndexEquivalent >=\n standardRange.minimum\n ) ||\n (\n direction === \"high\" &&\n exposureIndexEquivalent <=\n standardRange.maximum\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".exposureIndexEquivalent must lie outside the standard range in the declared direction.\"\n );\n }\n if (\n typeof record.autoIsoEligible !==\n \"boolean\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \".autoIsoEligible must be boolean.\"\n );\n }\n\n return {\n settingId:\n requireNonEmptyString(\n record.settingId,\n path + \".settingId\"\n ),\n label:\n requireNonEmptyString(\n record.label,\n path + \".label\"\n ),\n direction,\n exposureIndexEquivalent,\n autoIsoEligible:\n record.autoIsoEligible,\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\nfunction parseCaptureModePolicy(\n value: unknown,\n standardRange:\n IsoExposureIndexRange,\n expandedIds:\n ReadonlySet<string>,\n path: string\n): IsoCaptureModePolicy {\n const record =\n requireRecord(value, path, [\"standardExposureIndexRange\", \"expandedSettingIds\", \"captureModeId\", \"autoIso\", \"evidence\"]);\n const modeRange =\n parseRange(\n record\n .standardExposureIndexRange,\n path +\n \".standardExposureIndexRange\"\n );\n if (\n !rangeWithin(\n modeRange,\n standardRange\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".standardExposureIndexRange must lie inside the global standard range.\"\n );\n }\n if (\n !Array.isArray(\n record.expandedSettingIds\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".expandedSettingIds must be an array.\"\n );\n }\n const expandedSettingIds =\n record.expandedSettingIds.map(\n (entry, index) => {\n const id =\n requireNonEmptyString(\n entry,\n path +\n \".expandedSettingIds[\" +\n index +\n \"]\"\n );\n if (!expandedIds.has(id)) {\n throw new InvalidConfigurationError(\n path +\n \".expandedSettingIds contains an unknown settingId.\"\n );\n }\n return id;\n }\n );\n if (\n new Set(\n expandedSettingIds\n ).size !==\n expandedSettingIds.length\n ) {\n throw new InvalidConfigurationError(\n path +\n \".expandedSettingIds must not contain duplicates.\"\n );\n }\n\n return {\n captureModeId:\n requireNonEmptyString(\n record.captureModeId,\n path + \".captureModeId\"\n ),\n standardExposureIndexRange:\n modeRange,\n expandedSettingIds,\n autoIso:\n parseAutoIso(\n record.autoIso,\n modeRange,\n path + \".autoIso\"\n ),\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\n/**\n * Validates an untrusted declaration and returns the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected here.\n *\n * ISO is an exposure-index (EI) control setting. It does not create photons and says nothing about\n * read noise. Standard and expanded settings, limits per capture mode, and whether Auto ISO is\n * available are all stated explicitly. If availability is unknown, automatic control is not allowed.\n * @param value - unknown. Untrusted input; TypeScript types alone are not validation.\n * @returns IsoCapabilityProfile. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function parseIsoCapabilityProfile(\n value: unknown\n): IsoCapabilityProfile {\n const record =\n requireRecord(\n value,\n \"isoCapabilityProfile\", [\"schemaVersion\", \"capabilityMeaning\", \"standard\", \"expandedSettings\", \"captureModePolicies\", \"profileId\", \"profileVersion\", \"autoIso\", \"evidence\"]\n );\n if (\n record.schemaVersion !==\n ISO_CAPABILITY_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'isoCapabilityProfile.schemaVersion must be \"' +\n ISO_CAPABILITY_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n if (\n record.capabilityMeaning !==\n \"reported-exposure-index-capability-not-physical-gain\"\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.capabilityMeaning is invalid.\"\n );\n }\n const standard =\n requireRecord(\n record.standard,\n \"isoCapabilityProfile.standard\", [\"exposureIndexRange\", \"settingGrid\"]\n );\n const standardRange =\n parseRange(\n standard\n .exposureIndexRange,\n \"isoCapabilityProfile.standard.exposureIndexRange\"\n );\n const settingGrid =\n parseGrid(\n standard.settingGrid,\n standardRange,\n \"isoCapabilityProfile.standard.settingGrid\"\n );\n\n if (\n !Array.isArray(\n record.expandedSettings\n )\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.expandedSettings must be an array.\"\n );\n }\n const expandedSettings =\n record.expandedSettings.map(\n (entry, index) =>\n parseExpandedSetting(\n entry,\n standardRange,\n \"isoCapabilityProfile.expandedSettings[\" +\n index +\n \"]\"\n )\n );\n const expandedIds =\n expandedSettings.map(\n (entry) =>\n entry.settingId\n );\n if (\n new Set(expandedIds).size !==\n expandedIds.length\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.expandedSettings must not contain duplicate settingId values.\"\n );\n }\n const expandedIdSet =\n new Set(expandedIds);\n\n if (\n !Array.isArray(\n record.captureModePolicies\n )\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.captureModePolicies must be an array.\"\n );\n }\n const captureModePolicies =\n record.captureModePolicies.map(\n (entry, index) =>\n parseCaptureModePolicy(\n entry,\n standardRange,\n expandedIdSet,\n \"isoCapabilityProfile.captureModePolicies[\" +\n index +\n \"]\"\n )\n );\n const modeIds =\n captureModePolicies.map(\n (entry) =>\n entry.captureModeId\n );\n if (\n new Set(modeIds).size !==\n modeIds.length\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.captureModePolicies must not contain duplicate captureModeId values.\"\n );\n }\n\n return {\n schemaVersion:\n ISO_CAPABILITY_PROFILE_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"isoCapabilityProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"isoCapabilityProfile.profileVersion\"\n ),\n capabilityMeaning:\n \"reported-exposure-index-capability-not-physical-gain\",\n standard: {\n exposureIndexRange:\n standardRange,\n settingGrid\n },\n expandedSettings,\n autoIso:\n parseAutoIso(\n record.autoIso,\n standardRange,\n \"isoCapabilityProfile.autoIso\"\n ),\n captureModePolicies,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"isoCapabilityProfile.evidence\"\n )\n };\n}\n\nfunction isStandardValueSupported(\n value: number,\n range:\n IsoExposureIndexRange,\n grid:\n IsoStandardSettingGrid\n): boolean {\n if (\n value < range.minimum ||\n value > range.maximum\n ) {\n return false;\n }\n return (\n grid.kind ===\n \"continuous-within-range\" ||\n grid.values.includes(value)\n );\n}\n\nfunction resolveModePolicy(\n profile:\n IsoCapabilityProfile,\n captureModeId:\n string | undefined\n): {\n range:\n IsoExposureIndexRange;\n expandedSettingIds:\n ReadonlySet<string>;\n autoIso:\n IsoAutoIsoCapability;\n} {\n if (\n captureModeId ===\n undefined\n ) {\n return {\n range:\n profile.standard\n .exposureIndexRange,\n expandedSettingIds:\n new Set(\n profile\n .expandedSettings\n .map(\n (entry) =>\n entry.settingId\n )\n ),\n autoIso:\n profile.autoIso\n };\n }\n if (\n captureModeId.trim()\n .length === 0\n ) {\n throw new InvalidConfigurationError(\n \"captureModeId must be a non-empty string when provided.\"\n );\n }\n const policy =\n profile.captureModePolicies.find(\n (entry) =>\n entry.captureModeId ===\n captureModeId\n );\n if (policy === undefined) {\n return {\n range:\n profile.standard\n .exposureIndexRange,\n expandedSettingIds:\n new Set(\n profile\n .expandedSettings\n .map(\n (entry) =>\n entry.settingId\n )\n ),\n autoIso:\n profile.autoIso\n };\n }\n return {\n range:\n policy\n .standardExposureIndexRange,\n expandedSettingIds:\n new Set(\n policy\n .expandedSettingIds\n ),\n autoIso:\n policy.autoIso\n };\n}\n\n/**\n * Resolves one standard, expanded or Auto ISO request against what the profile and capture mode\n * declare as available. Reports \"unavailable\" or \"unknown\" explicitly.\n *\n * ISO is an exposure-index (EI) control setting. It does not create photons and says nothing about\n * read noise. Standard and expanded settings, limits per capture mode, and whether Auto ISO is\n * available are all stated explicitly. If availability is unknown, automatic control is not allowed.\n * @param input - ResolveIsoCapabilityInput. See that type for coordinates, units and profile binding.\n * @returns ResolvedIsoCapability. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function resolveIsoCapability(\n input:\n ResolveIsoCapabilityInput\n): ResolvedIsoCapability {\n requireInputKeys(input, \"resolveIsoCapability\", [\"profile\", \"setting\", \"captureModeId\"]);\n const profile =\n parseIsoCapabilityProfile(\n input.profile\n );\n const modePolicy =\n resolveModePolicy(\n profile,\n input.captureModeId\n );\n\n if (\n input.setting.kind ===\n \"standard\"\n ) {\n if (\n typeof input.setting\n .exposureIndex !==\n \"number\" ||\n !Number.isFinite(\n input.setting\n .exposureIndex\n ) ||\n input.setting\n .exposureIndex <= 0\n ) {\n throw new InvalidScientificInputError(\n \"standard exposureIndex must be finite and greater than zero.\"\n );\n }\n if (\n !isStandardValueSupported(\n input.setting\n .exposureIndex,\n modePolicy.range,\n profile.standard\n .settingGrid\n )\n ) {\n throw new InvalidScientificInputError(\n \"Requested standard exposure index is not supported by the selected ISO capability/mode.\"\n );\n }\n\n const autoEligible =\n modePolicy.autoIso\n .availability ===\n \"supported\" &&\n input.setting\n .exposureIndex >=\n modePolicy.autoIso\n .standardExposureIndexRange\n .minimum &&\n input.setting\n .exposureIndex <=\n modePolicy.autoIso\n .standardExposureIndexRange\n .maximum;\n\n return {\n profileId:\n profile.profileId,\n profileVersion:\n profile.profileVersion,\n captureModeId:\n input.captureModeId ??\n null,\n setting: {\n kind: \"standard\",\n exposureIndex:\n input.setting\n .exposureIndex\n },\n reportedExposureIndex:\n input.setting\n .exposureIndex,\n expandedSetting: false,\n autoIsoEligible:\n autoEligible,\n standardExposureIndexRange: {\n ...modePolicy.range\n },\n standardSettingGrid:\n profile.standard\n .settingGrid.kind ===\n \"continuous-within-range\"\n ? {\n kind:\n \"continuous-within-range\"\n }\n : {\n kind:\n \"discrete-values\",\n values: [\n ...profile.standard\n .settingGrid\n .values\n ]\n },\n autoIso:\n modePolicy.autoIso,\n capturedPhotonExpectationModified:\n false,\n photonShotNoiseStatisticsModified:\n false,\n physicalGainInferred:\n false,\n conversionGainInferred:\n false,\n readNoiseInferred:\n false,\n saturationInferred:\n false,\n exactCommercialCameraBehaviorClaimed:\n false\n };\n }\n\n if (\n input.setting.kind !==\n \"expanded\"\n ) {\n throw new InvalidConfigurationError(\n \"ISO setting must be a valid standard or expanded setting.\"\n );\n }\n const expandedSettingId =\n input.setting.settingId;\n if (\n typeof expandedSettingId !==\n \"string\" ||\n expandedSettingId.trim()\n .length === 0\n ) {\n throw new InvalidConfigurationError(\n \"ISO setting must be a valid standard or expanded setting.\"\n );\n }\n\n const setting =\n profile.expandedSettings.find(\n (entry) =>\n entry.settingId ===\n expandedSettingId\n );\n if (\n setting === undefined ||\n !modePolicy\n .expandedSettingIds\n .has(setting.settingId)\n ) {\n throw new InvalidScientificInputError(\n \"Requested expanded ISO setting is not supported by the selected ISO capability/mode.\"\n );\n }\n\n return {\n profileId:\n profile.profileId,\n profileVersion:\n profile.profileVersion,\n captureModeId:\n input.captureModeId ??\n null,\n setting: {\n kind: \"expanded\",\n settingId:\n setting.settingId,\n label: setting.label,\n direction:\n setting.direction,\n exposureIndexEquivalent:\n setting\n .exposureIndexEquivalent\n },\n reportedExposureIndex:\n setting\n .exposureIndexEquivalent,\n expandedSetting: true,\n autoIsoEligible:\n modePolicy.autoIso\n .availability ===\n \"supported\" &&\n setting.autoIsoEligible,\n standardExposureIndexRange: {\n ...modePolicy.range\n },\n standardSettingGrid:\n profile.standard\n .settingGrid.kind ===\n \"continuous-within-range\"\n ? {\n kind:\n \"continuous-within-range\"\n }\n : {\n kind:\n \"discrete-values\",\n values: [\n ...profile.standard\n .settingGrid.values\n ]\n },\n autoIso:\n modePolicy.autoIso,\n capturedPhotonExpectationModified:\n false,\n photonShotNoiseStatisticsModified:\n false,\n physicalGainInferred:\n false,\n conversionGainInferred:\n false,\n readNoiseInferred: false,\n saturationInferred: false,\n exactCommercialCameraBehaviorClaimed:\n false\n };\n}\n\n\nexport interface BindIsoCapabilityToExposureCapabilitiesInput {\n isoCapabilityProfile:\n IsoCapabilityProfile;\n equipmentCapabilities:\n ResolvedGenericEquipmentExposureCapabilities;\n captureModeId?: string;\n}\n\nexport interface BoundIsoExposureCapabilities {\n isoCapabilityProfileId: string;\n isoCapabilityProfileVersion: string;\n captureModeId: string | null;\n capabilities:\n ResolvedGenericEquipmentExposureCapabilities;\n expandedSettingsExcludedFromNumericExposureGrid:\n true;\n physicalGainInferred: false;\n readNoiseInferred: false;\n}\n\nfunction sameResolvedGrid(\n resolved:\n ResolvedNumericSettingGrid,\n detailed:\n IsoStandardSettingGrid\n): boolean {\n if (\n resolved.kind !==\n detailed.kind\n ) {\n return false;\n }\n if (\n resolved.kind ===\n \"continuous-within-range\" ||\n detailed.kind ===\n \"continuous-within-range\"\n ) {\n return true;\n }\n return (\n resolved.values.length ===\n detailed.values.length &&\n resolved.values.every(\n (value, index) =>\n value ===\n detailed.values[index]\n )\n );\n}\n\nfunction gridWithinRange(\n grid:\n ResolvedNumericSettingGrid,\n range:\n IsoExposureIndexRange\n): ResolvedNumericSettingGrid {\n if (\n grid.kind ===\n \"continuous-within-range\"\n ) {\n return {\n kind:\n \"continuous-within-range\"\n };\n }\n const values =\n grid.values.filter(\n (value) =>\n value >= range.minimum &&\n value <= range.maximum\n );\n if (values.length === 0) {\n throw new InvalidScientificInputError(\n \"Selected capture-mode ISO range contains no values from the resolved equipment ISO grid.\"\n );\n }\n return {\n kind: \"discrete-values\",\n values\n };\n}\n\n/**\n * Combines the detailed ISO/EI capability profile with the numeric capability\n * envelope that the exposure-mode resolvers use.\n *\n * The existing equipment capability must match the profile's global standard\n * ISO range and grid exactly. A capture-mode policy backed by evidence may\n * narrow the standard manual range for that mode. Auto ISO may be narrower\n * still. Expanded settings (such as L and H) stay outside the resolvers'\n * ordinary numeric ISO grid; use resolveIsoCapability() for them.\n */\nexport function bindIsoCapabilityToExposureCapabilities(\n input:\n BindIsoCapabilityToExposureCapabilitiesInput\n): BoundIsoExposureCapabilities {\n requireInputKeys(input, \"bindIsoCapabilityToExposureCapabilities\", [\"isoCapabilityProfile\", \"equipmentCapabilities\", \"captureModeId\"]);\n const profile =\n parseIsoCapabilityProfile(\n input.isoCapabilityProfile\n );\n const source =\n input.equipmentCapabilities;\n\n if (\n source.iso.minimum !==\n profile.standard\n .exposureIndexRange\n .minimum ||\n source.iso.maximum !==\n profile.standard\n .exposureIndexRange\n .maximum ||\n !sameResolvedGrid(\n source.iso.settingGrid,\n profile.standard\n .settingGrid\n )\n ) {\n throw new InvalidScientificInputError(\n \"Detailed ISO capability standard range/grid must exactly match the existing resolved equipment ISO capability.\"\n );\n }\n\n const modePolicy =\n resolveModePolicy(\n profile,\n input.captureModeId\n );\n const settingGrid =\n gridWithinRange(\n source.iso.settingGrid,\n modePolicy.range\n );\n\n const iso =\n modePolicy.autoIso\n .availability ===\n \"supported\"\n ? {\n minimum:\n modePolicy.range.minimum,\n maximum:\n modePolicy.range.maximum,\n settingGrid,\n autoIsoAvailability:\n \"supported\" as const,\n autoIsoMinimum:\n modePolicy.autoIso\n .standardExposureIndexRange\n .minimum,\n autoIsoMaximum:\n modePolicy.autoIso\n .standardExposureIndexRange\n .maximum\n }\n : {\n minimum:\n modePolicy.range.minimum,\n maximum:\n modePolicy.range.maximum,\n settingGrid,\n autoIsoAvailability:\n modePolicy.autoIso\n .availability\n };\n\n return {\n isoCapabilityProfileId:\n profile.profileId,\n isoCapabilityProfileVersion:\n profile.profileVersion,\n captureModeId:\n input.captureModeId ??\n null,\n capabilities: {\n ...source,\n iso\n },\n expandedSettingsExcludedFromNumericExposureGrid:\n true,\n physicalGainInferred:\n false,\n readNoiseInferred:\n false\n };\n}\n"]}
1
+ {"version":3,"file":"iso-capabilities.js","sourceRoot":"","sources":["../../src/equipment/iso-capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * ISO capabilities: which standard, expanded and Auto ISO settings a body offers, and in which\n * capture modes.\n *\n * The parser validates untrusted input and returns the normalized typed contract. Unknown enum\n * values, missing required fields and incompatible scientific data are rejected.\n *\n * ISO is an exposure-index (EI) control setting. It does not create photons and says nothing about\n * read noise. Standard and expanded settings, limits per capture mode, and whether Auto ISO is\n * available are all stated explicitly. If availability is unknown, automatic control is not allowed.\n * @see docs/GENERIC_TIER_PRESETS.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport type {\n ResolvedGenericEquipmentExposureCapabilities,\n ResolvedNumericSettingGrid\n} from \"./exposure-capabilities.js\";\nimport { requireInputKeys, rejectUnknownVariantFields, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, requireConfigPositiveFinite as requirePositiveFinite, parseConfigAvailability as parseAvailability } from \"../core/record-validation.js\";\nimport { parseRange } from \"./exposure-capabilities.js\";\n\nexport const ISO_CAPABILITY_PROFILE_SCHEMA_VERSION =\n \"0.1.0\" as const;\n\nexport type IsoCapabilityAvailability =\n | \"supported\"\n | \"unsupported\"\n | \"unknown\";\n\nexport interface IsoExposureIndexRange {\n minimum: number;\n maximum: number;\n}\n\nexport type IsoStandardSettingGrid =\n | {\n kind: \"continuous-within-range\";\n }\n | {\n kind: \"discrete-values\";\n values: readonly number[];\n };\n\nexport interface IsoExpandedSetting {\n settingId: string;\n label: string;\n direction: \"low\" | \"high\";\n exposureIndexEquivalent: number;\n autoIsoEligible: boolean;\n evidence: readonly EvidenceProvenance[];\n}\n\nexport type IsoAutoIsoCapability =\n | {\n availability: \"supported\";\n standardExposureIndexRange:\n IsoExposureIndexRange;\n evidence: readonly EvidenceProvenance[];\n }\n | {\n availability:\n | \"unsupported\"\n | \"unknown\";\n evidence: readonly EvidenceProvenance[];\n };\n\nexport interface IsoCaptureModePolicy {\n captureModeId: string;\n standardExposureIndexRange:\n IsoExposureIndexRange;\n expandedSettingIds:\n readonly string[];\n autoIso:\n IsoAutoIsoCapability;\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface IsoCapabilityProfile {\n schemaVersion:\n typeof ISO_CAPABILITY_PROFILE_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n capabilityMeaning:\n \"reported-exposure-index-capability-not-physical-gain\";\n standard: {\n exposureIndexRange:\n IsoExposureIndexRange;\n settingGrid:\n IsoStandardSettingGrid;\n };\n expandedSettings:\n readonly IsoExpandedSetting[];\n autoIso:\n IsoAutoIsoCapability;\n captureModePolicies:\n readonly IsoCaptureModePolicy[];\n evidence:\n readonly EvidenceProvenance[];\n}\n\nexport type RequestedIsoSetting =\n | {\n kind: \"standard\";\n exposureIndex: number;\n }\n | {\n kind: \"expanded\";\n settingId: string;\n };\n\nexport interface ResolveIsoCapabilityInput {\n profile:\n IsoCapabilityProfile;\n setting:\n RequestedIsoSetting;\n captureModeId?: string;\n}\n\nexport interface ResolvedIsoCapability {\n profileId: string;\n profileVersion: string;\n captureModeId: string | null;\n setting:\n | {\n kind: \"standard\";\n exposureIndex: number;\n }\n | {\n kind: \"expanded\";\n settingId: string;\n label: string;\n direction:\n \"low\" | \"high\";\n exposureIndexEquivalent:\n number;\n };\n reportedExposureIndex: number;\n expandedSetting: boolean;\n autoIsoEligible:\n boolean;\n standardExposureIndexRange:\n IsoExposureIndexRange;\n standardSettingGrid:\n IsoStandardSettingGrid;\n autoIso:\n IsoAutoIsoCapability;\n capturedPhotonExpectationModified:\n false;\n photonShotNoiseStatisticsModified:\n false;\n physicalGainInferred:\n false;\n conversionGainInferred:\n false;\n readNoiseInferred: false;\n saturationInferred: false;\n exactCommercialCameraBehaviorClaimed:\n false;\n}\n\nfunction rangeWithin(\n inner:\n IsoExposureIndexRange,\n outer:\n IsoExposureIndexRange\n): boolean {\n return (\n inner.minimum >=\n outer.minimum &&\n inner.maximum <=\n outer.maximum\n );\n}\n\nfunction parseGrid(\n value: unknown,\n range:\n IsoExposureIndexRange,\n path: string\n): IsoStandardSettingGrid {\n const record =\n requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", { \"continuous-within-range\": [\"kind\"], \"discrete-values\": [\"kind\", \"values\"] }, path);\n if (\n record.kind ===\n \"continuous-within-range\"\n ) {\n return {\n kind:\n \"continuous-within-range\"\n };\n }\n if (\n record.kind ===\n \"discrete-values\"\n ) {\n if (\n !Array.isArray(\n record.values\n ) ||\n record.values.length === 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must be a non-empty array.\"\n );\n }\n let previous =\n Number.NEGATIVE_INFINITY;\n const values =\n record.values.map(\n (entry, index) => {\n const parsed =\n requirePositiveFinite(\n entry,\n path +\n \".values[\" +\n index +\n \"]\"\n );\n if (\n parsed <= previous\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must be strictly increasing.\"\n );\n }\n if (\n parsed <\n range.minimum ||\n parsed >\n range.maximum\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must remain inside the standard ISO range.\"\n );\n }\n previous = parsed;\n return parsed;\n }\n );\n if (\n values[0] !==\n range.minimum ||\n values[\n values.length - 1\n ] !== range.maximum\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must include the exact standard range endpoints.\"\n );\n }\n return {\n kind:\n \"discrete-values\",\n values\n };\n }\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseAutoIso(\n value: unknown,\n standardRange:\n IsoExposureIndexRange,\n path: string\n): IsoAutoIsoCapability {\n const record =\n requireRecord(value, path, [\"availability\", \"evidence\", \"standardExposureIndexRange\"]);\n const availability =\n parseAvailability(\n record.availability,\n path + \".availability\"\n );\n const evidence =\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n );\n\n if (\n availability ===\n \"supported\"\n ) {\n const autoRange =\n parseRange(\n record\n .standardExposureIndexRange,\n path +\n \".standardExposureIndexRange\"\n );\n if (\n !rangeWithin(\n autoRange,\n standardRange\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".standardExposureIndexRange must lie inside the standard ISO range.\"\n );\n }\n return {\n availability:\n \"supported\",\n standardExposureIndexRange:\n autoRange,\n evidence\n };\n }\n\n if (\n record\n .standardExposureIndexRange !==\n undefined\n ) {\n throw new InvalidConfigurationError(\n path +\n \".standardExposureIndexRange must be omitted unless Auto ISO is supported.\"\n );\n }\n\n return {\n availability,\n evidence\n };\n}\n\nfunction parseExpandedSetting(\n value: unknown,\n standardRange:\n IsoExposureIndexRange,\n path: string\n): IsoExpandedSetting {\n const record =\n requireRecord(value, path, [\"direction\", \"exposureIndexEquivalent\", \"autoIsoEligible\", \"settingId\", \"label\", \"evidence\"]);\n const direction =\n record.direction;\n if (\n direction !== \"low\" &&\n direction !== \"high\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \".direction must be low or high.\"\n );\n }\n const exposureIndexEquivalent =\n requirePositiveFinite(\n record\n .exposureIndexEquivalent,\n path +\n \".exposureIndexEquivalent\"\n );\n if (\n (\n direction === \"low\" &&\n exposureIndexEquivalent >=\n standardRange.minimum\n ) ||\n (\n direction === \"high\" &&\n exposureIndexEquivalent <=\n standardRange.maximum\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".exposureIndexEquivalent must lie outside the standard range in the declared direction.\"\n );\n }\n if (\n typeof record.autoIsoEligible !==\n \"boolean\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \".autoIsoEligible must be boolean.\"\n );\n }\n\n return {\n settingId:\n requireNonEmptyString(\n record.settingId,\n path + \".settingId\"\n ),\n label:\n requireNonEmptyString(\n record.label,\n path + \".label\"\n ),\n direction,\n exposureIndexEquivalent,\n autoIsoEligible:\n record.autoIsoEligible,\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\nfunction parseCaptureModePolicy(\n value: unknown,\n standardRange:\n IsoExposureIndexRange,\n expandedIds:\n ReadonlySet<string>,\n path: string\n): IsoCaptureModePolicy {\n const record =\n requireRecord(value, path, [\"standardExposureIndexRange\", \"expandedSettingIds\", \"captureModeId\", \"autoIso\", \"evidence\"]);\n const modeRange =\n parseRange(\n record\n .standardExposureIndexRange,\n path +\n \".standardExposureIndexRange\"\n );\n if (\n !rangeWithin(\n modeRange,\n standardRange\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".standardExposureIndexRange must lie inside the global standard range.\"\n );\n }\n if (\n !Array.isArray(\n record.expandedSettingIds\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".expandedSettingIds must be an array.\"\n );\n }\n const expandedSettingIds =\n record.expandedSettingIds.map(\n (entry, index) => {\n const id =\n requireNonEmptyString(\n entry,\n path +\n \".expandedSettingIds[\" +\n index +\n \"]\"\n );\n if (!expandedIds.has(id)) {\n throw new InvalidConfigurationError(\n path +\n \".expandedSettingIds contains an unknown settingId.\"\n );\n }\n return id;\n }\n );\n if (\n new Set(\n expandedSettingIds\n ).size !==\n expandedSettingIds.length\n ) {\n throw new InvalidConfigurationError(\n path +\n \".expandedSettingIds must not contain duplicates.\"\n );\n }\n\n return {\n captureModeId:\n requireNonEmptyString(\n record.captureModeId,\n path + \".captureModeId\"\n ),\n standardExposureIndexRange:\n modeRange,\n expandedSettingIds,\n autoIso:\n parseAutoIso(\n record.autoIso,\n modeRange,\n path + \".autoIso\"\n ),\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\n/**\n * Validates an untrusted declaration and returns the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected here.\n *\n * ISO is an exposure-index (EI) control setting. It does not create photons and says nothing about\n * read noise. Standard and expanded settings, limits per capture mode, and whether Auto ISO is\n * available are all stated explicitly. If availability is unknown, automatic control is not allowed.\n * @param value - unknown. Untrusted input; TypeScript types alone are not validation.\n * @returns IsoCapabilityProfile. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function parseIsoCapabilityProfile(\n value: unknown\n): IsoCapabilityProfile {\n const record =\n requireRecord(\n value,\n \"isoCapabilityProfile\", [\"schemaVersion\", \"capabilityMeaning\", \"standard\", \"expandedSettings\", \"captureModePolicies\", \"profileId\", \"profileVersion\", \"autoIso\", \"evidence\"]\n );\n if (\n record.schemaVersion !==\n ISO_CAPABILITY_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'isoCapabilityProfile.schemaVersion must be \"' +\n ISO_CAPABILITY_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n if (\n record.capabilityMeaning !==\n \"reported-exposure-index-capability-not-physical-gain\"\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.capabilityMeaning is invalid.\"\n );\n }\n const standard =\n requireRecord(\n record.standard,\n \"isoCapabilityProfile.standard\", [\"exposureIndexRange\", \"settingGrid\"]\n );\n const standardRange =\n parseRange(\n standard\n .exposureIndexRange,\n \"isoCapabilityProfile.standard.exposureIndexRange\"\n );\n const settingGrid =\n parseGrid(\n standard.settingGrid,\n standardRange,\n \"isoCapabilityProfile.standard.settingGrid\"\n );\n\n if (\n !Array.isArray(\n record.expandedSettings\n )\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.expandedSettings must be an array.\"\n );\n }\n const expandedSettings =\n record.expandedSettings.map(\n (entry, index) =>\n parseExpandedSetting(\n entry,\n standardRange,\n \"isoCapabilityProfile.expandedSettings[\" +\n index +\n \"]\"\n )\n );\n const expandedIds =\n expandedSettings.map(\n (entry) =>\n entry.settingId\n );\n if (\n new Set(expandedIds).size !==\n expandedIds.length\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.expandedSettings must not contain duplicate settingId values.\"\n );\n }\n const expandedIdSet =\n new Set(expandedIds);\n\n if (\n !Array.isArray(\n record.captureModePolicies\n )\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.captureModePolicies must be an array.\"\n );\n }\n const captureModePolicies =\n record.captureModePolicies.map(\n (entry, index) =>\n parseCaptureModePolicy(\n entry,\n standardRange,\n expandedIdSet,\n \"isoCapabilityProfile.captureModePolicies[\" +\n index +\n \"]\"\n )\n );\n const modeIds =\n captureModePolicies.map(\n (entry) =>\n entry.captureModeId\n );\n if (\n new Set(modeIds).size !==\n modeIds.length\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.captureModePolicies must not contain duplicate captureModeId values.\"\n );\n }\n\n return {\n schemaVersion:\n ISO_CAPABILITY_PROFILE_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"isoCapabilityProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"isoCapabilityProfile.profileVersion\"\n ),\n capabilityMeaning:\n \"reported-exposure-index-capability-not-physical-gain\",\n standard: {\n exposureIndexRange:\n standardRange,\n settingGrid\n },\n expandedSettings,\n autoIso:\n parseAutoIso(\n record.autoIso,\n standardRange,\n \"isoCapabilityProfile.autoIso\"\n ),\n captureModePolicies,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"isoCapabilityProfile.evidence\"\n )\n };\n}\n\nfunction isStandardValueSupported(\n value: number,\n range:\n IsoExposureIndexRange,\n grid:\n IsoStandardSettingGrid\n): boolean {\n if (\n value < range.minimum ||\n value > range.maximum\n ) {\n return false;\n }\n return (\n grid.kind ===\n \"continuous-within-range\" ||\n grid.values.includes(value)\n );\n}\n\nfunction resolveModePolicy(\n profile:\n IsoCapabilityProfile,\n captureModeId:\n string | undefined\n): {\n range:\n IsoExposureIndexRange;\n expandedSettingIds:\n ReadonlySet<string>;\n autoIso:\n IsoAutoIsoCapability;\n} {\n if (\n captureModeId ===\n undefined\n ) {\n return {\n range:\n profile.standard\n .exposureIndexRange,\n expandedSettingIds:\n new Set(\n profile\n .expandedSettings\n .map(\n (entry) =>\n entry.settingId\n )\n ),\n autoIso:\n profile.autoIso\n };\n }\n if (\n captureModeId.trim()\n .length === 0\n ) {\n throw new InvalidConfigurationError(\n \"captureModeId must be a non-empty string when provided.\"\n );\n }\n const policy =\n profile.captureModePolicies.find(\n (entry) =>\n entry.captureModeId ===\n captureModeId\n );\n if (policy === undefined) {\n return {\n range:\n profile.standard\n .exposureIndexRange,\n expandedSettingIds:\n new Set(\n profile\n .expandedSettings\n .map(\n (entry) =>\n entry.settingId\n )\n ),\n autoIso:\n profile.autoIso\n };\n }\n return {\n range:\n policy\n .standardExposureIndexRange,\n expandedSettingIds:\n new Set(\n policy\n .expandedSettingIds\n ),\n autoIso:\n policy.autoIso\n };\n}\n\n/**\n * Resolves one standard, expanded or Auto ISO request against what the profile and capture mode\n * declare as available. Reports \"unavailable\" or \"unknown\" explicitly.\n *\n * ISO is an exposure-index (EI) control setting. It does not create photons and says nothing about\n * read noise. Standard and expanded settings, limits per capture mode, and whether Auto ISO is\n * available are all stated explicitly. If availability is unknown, automatic control is not allowed.\n * @param input - ResolveIsoCapabilityInput. See that type for coordinates, units and profile binding.\n * @returns ResolvedIsoCapability. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function resolveIsoCapability(\n input:\n ResolveIsoCapabilityInput\n): ResolvedIsoCapability {\n requireInputKeys(input, \"resolveIsoCapability\", [\"profile\", \"setting\", \"captureModeId\"]);\n const profile =\n parseIsoCapabilityProfile(\n input.profile\n );\n const modePolicy =\n resolveModePolicy(\n profile,\n input.captureModeId\n );\n\n if (\n input.setting.kind ===\n \"standard\"\n ) {\n if (\n typeof input.setting\n .exposureIndex !==\n \"number\" ||\n !Number.isFinite(\n input.setting\n .exposureIndex\n ) ||\n input.setting\n .exposureIndex <= 0\n ) {\n throw new InvalidScientificInputError(\n \"standard exposureIndex must be finite and greater than zero.\"\n );\n }\n if (\n !isStandardValueSupported(\n input.setting\n .exposureIndex,\n modePolicy.range,\n profile.standard\n .settingGrid\n )\n ) {\n throw new InvalidScientificInputError(\n \"Requested standard exposure index is not supported by the selected ISO capability/mode.\"\n );\n }\n\n const autoEligible =\n modePolicy.autoIso\n .availability ===\n \"supported\" &&\n input.setting\n .exposureIndex >=\n modePolicy.autoIso\n .standardExposureIndexRange\n .minimum &&\n input.setting\n .exposureIndex <=\n modePolicy.autoIso\n .standardExposureIndexRange\n .maximum;\n\n return {\n profileId:\n profile.profileId,\n profileVersion:\n profile.profileVersion,\n captureModeId:\n input.captureModeId ??\n null,\n setting: {\n kind: \"standard\",\n exposureIndex:\n input.setting\n .exposureIndex\n },\n reportedExposureIndex:\n input.setting\n .exposureIndex,\n expandedSetting: false,\n autoIsoEligible:\n autoEligible,\n standardExposureIndexRange: {\n ...modePolicy.range\n },\n standardSettingGrid:\n profile.standard\n .settingGrid.kind ===\n \"continuous-within-range\"\n ? {\n kind:\n \"continuous-within-range\"\n }\n : {\n kind:\n \"discrete-values\",\n values: [\n ...profile.standard\n .settingGrid\n .values\n ]\n },\n autoIso:\n modePolicy.autoIso,\n capturedPhotonExpectationModified:\n false,\n photonShotNoiseStatisticsModified:\n false,\n physicalGainInferred:\n false,\n conversionGainInferred:\n false,\n readNoiseInferred:\n false,\n saturationInferred:\n false,\n exactCommercialCameraBehaviorClaimed:\n false\n };\n }\n\n if (\n input.setting.kind !==\n \"expanded\"\n ) {\n throw new InvalidConfigurationError(\n \"ISO setting must be a valid standard or expanded setting.\"\n );\n }\n const expandedSettingId =\n input.setting.settingId;\n if (\n typeof expandedSettingId !==\n \"string\" ||\n expandedSettingId.trim()\n .length === 0\n ) {\n throw new InvalidConfigurationError(\n \"ISO setting must be a valid standard or expanded setting.\"\n );\n }\n\n const setting =\n profile.expandedSettings.find(\n (entry) =>\n entry.settingId ===\n expandedSettingId\n );\n if (\n setting === undefined ||\n !modePolicy\n .expandedSettingIds\n .has(setting.settingId)\n ) {\n throw new InvalidScientificInputError(\n \"Requested expanded ISO setting is not supported by the selected ISO capability/mode.\"\n );\n }\n\n return {\n profileId:\n profile.profileId,\n profileVersion:\n profile.profileVersion,\n captureModeId:\n input.captureModeId ??\n null,\n setting: {\n kind: \"expanded\",\n settingId:\n setting.settingId,\n label: setting.label,\n direction:\n setting.direction,\n exposureIndexEquivalent:\n setting\n .exposureIndexEquivalent\n },\n reportedExposureIndex:\n setting\n .exposureIndexEquivalent,\n expandedSetting: true,\n autoIsoEligible:\n modePolicy.autoIso\n .availability ===\n \"supported\" &&\n setting.autoIsoEligible,\n standardExposureIndexRange: {\n ...modePolicy.range\n },\n standardSettingGrid:\n profile.standard\n .settingGrid.kind ===\n \"continuous-within-range\"\n ? {\n kind:\n \"continuous-within-range\"\n }\n : {\n kind:\n \"discrete-values\",\n values: [\n ...profile.standard\n .settingGrid.values\n ]\n },\n autoIso:\n modePolicy.autoIso,\n capturedPhotonExpectationModified:\n false,\n photonShotNoiseStatisticsModified:\n false,\n physicalGainInferred:\n false,\n conversionGainInferred:\n false,\n readNoiseInferred: false,\n saturationInferred: false,\n exactCommercialCameraBehaviorClaimed:\n false\n };\n}\n\nexport interface BindIsoCapabilityToExposureCapabilitiesInput {\n isoCapabilityProfile:\n IsoCapabilityProfile;\n equipmentCapabilities:\n ResolvedGenericEquipmentExposureCapabilities;\n captureModeId?: string;\n}\n\nexport interface BoundIsoExposureCapabilities {\n isoCapabilityProfileId: string;\n isoCapabilityProfileVersion: string;\n captureModeId: string | null;\n capabilities:\n ResolvedGenericEquipmentExposureCapabilities;\n expandedSettingsExcludedFromNumericExposureGrid:\n true;\n physicalGainInferred: false;\n readNoiseInferred: false;\n}\n\nfunction sameResolvedGrid(\n resolved:\n ResolvedNumericSettingGrid,\n detailed:\n IsoStandardSettingGrid\n): boolean {\n if (\n resolved.kind !==\n detailed.kind\n ) {\n return false;\n }\n if (\n resolved.kind ===\n \"continuous-within-range\" ||\n detailed.kind ===\n \"continuous-within-range\"\n ) {\n return true;\n }\n return (\n resolved.values.length ===\n detailed.values.length &&\n resolved.values.every(\n (value, index) =>\n value ===\n detailed.values[index]\n )\n );\n}\n\nfunction gridWithinRange(\n grid:\n ResolvedNumericSettingGrid,\n range:\n IsoExposureIndexRange\n): ResolvedNumericSettingGrid {\n if (\n grid.kind ===\n \"continuous-within-range\"\n ) {\n return {\n kind:\n \"continuous-within-range\"\n };\n }\n const values =\n grid.values.filter(\n (value) =>\n value >= range.minimum &&\n value <= range.maximum\n );\n if (values.length === 0) {\n throw new InvalidScientificInputError(\n \"Selected capture-mode ISO range contains no values from the resolved equipment ISO grid.\"\n );\n }\n return {\n kind: \"discrete-values\",\n values\n };\n}\n\n/**\n * Combines the detailed ISO/EI capability profile with the numeric capability\n * envelope that the exposure-mode resolvers use.\n *\n * The existing equipment capability must match the profile's global standard\n * ISO range and grid exactly. A capture-mode policy backed by evidence may\n * narrow the standard manual range for that mode. Auto ISO may be narrower\n * still. Expanded settings (such as L and H) stay outside the resolvers'\n * ordinary numeric ISO grid; use resolveIsoCapability() for them.\n */\nexport function bindIsoCapabilityToExposureCapabilities(\n input:\n BindIsoCapabilityToExposureCapabilitiesInput\n): BoundIsoExposureCapabilities {\n requireInputKeys(input, \"bindIsoCapabilityToExposureCapabilities\", [\"isoCapabilityProfile\", \"equipmentCapabilities\", \"captureModeId\"]);\n const profile =\n parseIsoCapabilityProfile(\n input.isoCapabilityProfile\n );\n const source =\n input.equipmentCapabilities;\n\n if (\n source.iso.minimum !==\n profile.standard\n .exposureIndexRange\n .minimum ||\n source.iso.maximum !==\n profile.standard\n .exposureIndexRange\n .maximum ||\n !sameResolvedGrid(\n source.iso.settingGrid,\n profile.standard\n .settingGrid\n )\n ) {\n throw new InvalidScientificInputError(\n \"Detailed ISO capability standard range/grid must exactly match the existing resolved equipment ISO capability.\"\n );\n }\n\n const modePolicy =\n resolveModePolicy(\n profile,\n input.captureModeId\n );\n const settingGrid =\n gridWithinRange(\n source.iso.settingGrid,\n modePolicy.range\n );\n\n const iso =\n modePolicy.autoIso\n .availability ===\n \"supported\"\n ? {\n minimum:\n modePolicy.range.minimum,\n maximum:\n modePolicy.range.maximum,\n settingGrid,\n autoIsoAvailability:\n \"supported\" as const,\n autoIsoMinimum:\n modePolicy.autoIso\n .standardExposureIndexRange\n .minimum,\n autoIsoMaximum:\n modePolicy.autoIso\n .standardExposureIndexRange\n .maximum\n }\n : {\n minimum:\n modePolicy.range.minimum,\n maximum:\n modePolicy.range.maximum,\n settingGrid,\n autoIsoAvailability:\n modePolicy.autoIso\n .availability\n };\n\n return {\n isoCapabilityProfileId:\n profile.profileId,\n isoCapabilityProfileVersion:\n profile.profileVersion,\n captureModeId:\n input.captureModeId ??\n null,\n capabilities: {\n ...source,\n iso\n },\n expandedSettingsExcludedFromNumericExposureGrid:\n true,\n physicalGainInferred:\n false,\n readNoiseInferred:\n false\n };\n}\n"]}
@@ -12,7 +12,7 @@ import { InvalidConfigurationError } from "../core/configuration-error.js";
12
12
  import { parseEvidenceList } from "../core/evidence-provenance.js";
13
13
  import { InvalidScientificInputError } from "../core/validation.js";
14
14
  import { parseExposureMeteringProfile } from "../exposure/metering.js";
15
- import { requireInputKeys, rejectUnknownFields } from "../core/record-validation.js";
15
+ import { requireInputKeys, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, parseConfigAvailability as parseAvailability } from "../core/record-validation.js";
16
16
  export const GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION = "0.1.0";
17
17
  const POLICY_KINDS = new Set([
18
18
  "multi-zone-uniform",
@@ -21,31 +21,6 @@ const POLICY_KINDS = new Set([
21
21
  "highlight-weighted",
22
22
  "highlight-priority"
23
23
  ]);
24
- function requireRecord(value, path, allowedKeys) {
25
- if (typeof value !== "object" ||
26
- value === null ||
27
- Array.isArray(value)) {
28
- throw new InvalidConfigurationError(path + " must be an object.");
29
- }
30
- if (allowedKeys !== null)
31
- rejectUnknownFields(value, allowedKeys, path);
32
- return value;
33
- }
34
- function requireNonEmptyString(value, path) {
35
- if (typeof value !== "string" ||
36
- value.trim().length === 0) {
37
- throw new InvalidConfigurationError(path + " must be a non-empty string.");
38
- }
39
- return value.trim();
40
- }
41
- function parseAvailability(value, path) {
42
- if (value !== "supported" &&
43
- value !== "unsupported" &&
44
- value !== "unknown") {
45
- throw new InvalidConfigurationError(path + " is invalid.");
46
- }
47
- return value;
48
- }
49
24
  function parsePolicyKind(value, path) {
50
25
  if (typeof value !== "string" ||
51
26
  !POLICY_KINDS.has(value)) {
@@ -1 +1 @@
1
- {"version":3,"file":"metering-capabilities.js","sourceRoot":"","sources":["../../src/equipment/metering-capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Metering capabilities of a generic body: which of the engine's metering profiles and modes it can\n * select.\n *\n * This profile deliberately does not copy target or calibration values from those metering profiles.\n * The metering profile stays the single source of its calibration and target policy.\n * @see docs/GENERIC_TIER_PRESETS.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport {\n parseExposureMeteringProfile,\n type ExposureMeteringPolicy,\n type ExposureMeteringProfile\n} from \"../exposure/metering.js\";\nimport type { GenericCapabilityAvailability } from \"./exposure-capabilities.js\";\nimport { requireInputKeys, rejectUnknownFields } from \"../core/record-validation.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport const GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION =\n \"0.1.0\" as const;\n\nexport interface GenericSupportedMeteringProfile {\n meteringProfileId: string;\n policyKind: ExposureMeteringPolicy[\"kind\"];\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface GenericBodyMeteringCapabilityProfile {\n schemaVersion:\n typeof GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n scientificStatus: \"approximation\";\n evidence: readonly EvidenceProvenance[];\n supportedMeteringProfiles:\n readonly GenericSupportedMeteringProfile[];\n spotFocusPointLinkage: {\n availability: GenericCapabilityAvailability;\n evidence: readonly EvidenceProvenance[];\n };\n}\n\nexport type MeteringCapabilityCompatibilityBlocker =\n | \"metering-profile-unsupported\"\n | \"metering-policy-mismatch\";\n\nexport interface MeteringCapabilityCompatibilityAssessment {\n schemaVersion:\n typeof GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION;\n status: \"compatible\" | \"blocked\";\n bodyProfile: {\n profileId: string;\n profileVersion: string;\n };\n meteringProfile: {\n profileId: string;\n policyKind: ExposureMeteringPolicy[\"kind\"];\n };\n targetPolicyOwnership: \"metering-profile\";\n targetCalibrationDuplicatedInEquipmentProfile: false;\n spotFocusPointLinkageAvailability:\n GenericCapabilityAvailability;\n blockers:\n readonly MeteringCapabilityCompatibilityBlocker[];\n}\n\nexport interface AssessExposureMeteringProfileCompatibilityInput {\n bodyCapabilities:\n GenericBodyMeteringCapabilityProfile;\n meteringProfile:\n ExposureMeteringProfile;\n}\n\nconst POLICY_KINDS =\n new Set<ExposureMeteringPolicy[\"kind\"]>([\n \"multi-zone-uniform\",\n \"center-weighted-radial\",\n \"spot\",\n \"highlight-weighted\",\n \"highlight-priority\"\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 parseAvailability(\n value: unknown,\n path: string\n): GenericCapabilityAvailability {\n if (\n value !== \"supported\" &&\n value !== \"unsupported\" &&\n value !== \"unknown\"\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value;\n}\n\nfunction parsePolicyKind(\n value: unknown,\n path: string\n): ExposureMeteringPolicy[\"kind\"] {\n if (\n typeof value !== \"string\" ||\n !POLICY_KINDS.has(\n value as ExposureMeteringPolicy[\"kind\"]\n )\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value as ExposureMeteringPolicy[\"kind\"];\n}\n\n/**\n * Parses generic body metering capability metadata.\n *\n * This profile declares which of the engine's metering profiles and modes a\n * generic body can select. It deliberately does not copy target or\n * calibration values from those metering profiles.\n */\nexport function parseGenericBodyMeteringCapabilityProfile(\n value: unknown\n): GenericBodyMeteringCapabilityProfile {\n const record = requireRecord(\n value,\n \"genericBodyMeteringCapabilityProfile\", [\"schemaVersion\", \"scientificStatus\", \"supportedMeteringProfiles\", \"spotFocusPointLinkage\", \"profileId\", \"profileVersion\", \"evidence\"]\n );\n\n if (\n record.schemaVersion !==\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'genericBodyMeteringCapabilityProfile.schemaVersion must be \"' +\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION +\n '\".'\n );\n }\n if (\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n 'genericBodyMeteringCapabilityProfile.scientificStatus must be \"approximation\".'\n );\n }\n\n if (\n !Array.isArray(\n record.supportedMeteringProfiles\n ) ||\n record.supportedMeteringProfiles\n .length === 0\n ) {\n throw new InvalidConfigurationError(\n \"genericBodyMeteringCapabilityProfile.supportedMeteringProfiles must be a non-empty array.\"\n );\n }\n\n const supported =\n record.supportedMeteringProfiles.map(\n (entry, index) => {\n const path =\n \"genericBodyMeteringCapabilityProfile.supportedMeteringProfiles[\" +\n index +\n \"]\";\n const item =\n requireRecord(entry, path, [\"meteringProfileId\", \"policyKind\", \"evidence\"]);\n return {\n meteringProfileId:\n requireNonEmptyString(\n item.meteringProfileId,\n path + \".meteringProfileId\"\n ),\n policyKind:\n parsePolicyKind(\n item.policyKind,\n path + \".policyKind\"\n ),\n evidence:\n parseEvidenceList(\n item.evidence,\n path + \".evidence\"\n )\n };\n }\n );\n\n const ids =\n supported.map(\n (entry) =>\n entry.meteringProfileId\n );\n if (\n new Set(ids).size !==\n ids.length\n ) {\n throw new InvalidConfigurationError(\n \"genericBodyMeteringCapabilityProfile.supportedMeteringProfiles must not contain duplicate meteringProfileId values.\"\n );\n }\n\n const spotLink =\n requireRecord(\n record.spotFocusPointLinkage,\n \"genericBodyMeteringCapabilityProfile.spotFocusPointLinkage\", [\"availability\", \"evidence\"]\n );\n\n return {\n schemaVersion:\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"genericBodyMeteringCapabilityProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"genericBodyMeteringCapabilityProfile.profileVersion\"\n ),\n scientificStatus:\n \"approximation\",\n evidence:\n parseEvidenceList(\n record.evidence,\n \"genericBodyMeteringCapabilityProfile.evidence\"\n ),\n supportedMeteringProfiles:\n supported,\n spotFocusPointLinkage: {\n availability:\n parseAvailability(\n spotLink.availability,\n \"genericBodyMeteringCapabilityProfile.spotFocusPointLinkage.availability\"\n ),\n evidence:\n parseEvidenceList(\n spotLink.evidence,\n \"genericBodyMeteringCapabilityProfile.spotFocusPointLinkage.evidence\"\n )\n }\n };\n}\n\n/**\n * Checks whether one engine metering profile is selectable on a generic body.\n *\n * The metering profile stays the single source of its calibration and target\n * policy. They are never copied into equipment capability metadata.\n */\nexport function assessExposureMeteringProfileCompatibility(\n input:\n AssessExposureMeteringProfileCompatibilityInput\n): MeteringCapabilityCompatibilityAssessment {\n requireInputKeys(input, \"assessExposureMeteringProfileCompatibility\", [\"bodyCapabilities\", \"meteringProfile\"]);\n const body =\n parseGenericBodyMeteringCapabilityProfile(\n input.bodyCapabilities\n );\n const metering =\n parseExposureMeteringProfile(\n input.meteringProfile\n );\n\n const declared =\n body.supportedMeteringProfiles.find(\n (entry) =>\n entry.meteringProfileId ===\n metering.profileId\n );\n\n const blockers:\n MeteringCapabilityCompatibilityBlocker[] =\n [];\n\n if (declared === undefined) {\n blockers.push(\n \"metering-profile-unsupported\"\n );\n } else if (\n declared.policyKind !==\n metering.policy.kind\n ) {\n blockers.push(\n \"metering-policy-mismatch\"\n );\n }\n\n if (\n blockers.length >\n new Set(blockers).size\n ) {\n throw new InvalidScientificInputError(\n \"Metering capability compatibility blockers must remain unique.\"\n );\n }\n\n return {\n schemaVersion:\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION,\n status:\n blockers.length === 0\n ? \"compatible\"\n : \"blocked\",\n bodyProfile: {\n profileId: body.profileId,\n profileVersion:\n body.profileVersion\n },\n meteringProfile: {\n profileId:\n metering.profileId,\n policyKind:\n metering.policy.kind\n },\n targetPolicyOwnership:\n \"metering-profile\",\n targetCalibrationDuplicatedInEquipmentProfile:\n false,\n spotFocusPointLinkageAvailability:\n body.spotFocusPointLinkage\n .availability,\n blockers\n };\n}\n"]}
1
+ {"version":3,"file":"metering-capabilities.js","sourceRoot":"","sources":["../../src/equipment/metering-capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Metering capabilities of a generic body: which of the engine's metering profiles and modes it can\n * select.\n *\n * This profile deliberately does not copy target or calibration values from those metering profiles.\n * The metering profile stays the single source of its calibration and target policy.\n * @see docs/GENERIC_TIER_PRESETS.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport {\n parseExposureMeteringProfile,\n type ExposureMeteringPolicy,\n type ExposureMeteringProfile\n} from \"../exposure/metering.js\";\nimport type { GenericCapabilityAvailability } from \"./exposure-capabilities.js\";\nimport { requireInputKeys, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, parseConfigAvailability as parseAvailability } from \"../core/record-validation.js\";\n\n\nexport const GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION =\n \"0.1.0\" as const;\n\nexport interface GenericSupportedMeteringProfile {\n meteringProfileId: string;\n policyKind: ExposureMeteringPolicy[\"kind\"];\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface GenericBodyMeteringCapabilityProfile {\n schemaVersion:\n typeof GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n scientificStatus: \"approximation\";\n evidence: readonly EvidenceProvenance[];\n supportedMeteringProfiles:\n readonly GenericSupportedMeteringProfile[];\n spotFocusPointLinkage: {\n availability: GenericCapabilityAvailability;\n evidence: readonly EvidenceProvenance[];\n };\n}\n\nexport type MeteringCapabilityCompatibilityBlocker =\n | \"metering-profile-unsupported\"\n | \"metering-policy-mismatch\";\n\nexport interface MeteringCapabilityCompatibilityAssessment {\n schemaVersion:\n typeof GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION;\n status: \"compatible\" | \"blocked\";\n bodyProfile: {\n profileId: string;\n profileVersion: string;\n };\n meteringProfile: {\n profileId: string;\n policyKind: ExposureMeteringPolicy[\"kind\"];\n };\n targetPolicyOwnership: \"metering-profile\";\n targetCalibrationDuplicatedInEquipmentProfile: false;\n spotFocusPointLinkageAvailability:\n GenericCapabilityAvailability;\n blockers:\n readonly MeteringCapabilityCompatibilityBlocker[];\n}\n\nexport interface AssessExposureMeteringProfileCompatibilityInput {\n bodyCapabilities:\n GenericBodyMeteringCapabilityProfile;\n meteringProfile:\n ExposureMeteringProfile;\n}\n\nconst POLICY_KINDS =\n new Set<ExposureMeteringPolicy[\"kind\"]>([\n \"multi-zone-uniform\",\n \"center-weighted-radial\",\n \"spot\",\n \"highlight-weighted\",\n \"highlight-priority\"\n ]);\n\nfunction parsePolicyKind(\n value: unknown,\n path: string\n): ExposureMeteringPolicy[\"kind\"] {\n if (\n typeof value !== \"string\" ||\n !POLICY_KINDS.has(\n value as ExposureMeteringPolicy[\"kind\"]\n )\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value as ExposureMeteringPolicy[\"kind\"];\n}\n\n/**\n * Parses generic body metering capability metadata.\n *\n * This profile declares which of the engine's metering profiles and modes a\n * generic body can select. It deliberately does not copy target or\n * calibration values from those metering profiles.\n */\nexport function parseGenericBodyMeteringCapabilityProfile(\n value: unknown\n): GenericBodyMeteringCapabilityProfile {\n const record = requireRecord(\n value,\n \"genericBodyMeteringCapabilityProfile\", [\"schemaVersion\", \"scientificStatus\", \"supportedMeteringProfiles\", \"spotFocusPointLinkage\", \"profileId\", \"profileVersion\", \"evidence\"]\n );\n\n if (\n record.schemaVersion !==\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'genericBodyMeteringCapabilityProfile.schemaVersion must be \"' +\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION +\n '\".'\n );\n }\n if (\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n 'genericBodyMeteringCapabilityProfile.scientificStatus must be \"approximation\".'\n );\n }\n\n if (\n !Array.isArray(\n record.supportedMeteringProfiles\n ) ||\n record.supportedMeteringProfiles\n .length === 0\n ) {\n throw new InvalidConfigurationError(\n \"genericBodyMeteringCapabilityProfile.supportedMeteringProfiles must be a non-empty array.\"\n );\n }\n\n const supported =\n record.supportedMeteringProfiles.map(\n (entry, index) => {\n const path =\n \"genericBodyMeteringCapabilityProfile.supportedMeteringProfiles[\" +\n index +\n \"]\";\n const item =\n requireRecord(entry, path, [\"meteringProfileId\", \"policyKind\", \"evidence\"]);\n return {\n meteringProfileId:\n requireNonEmptyString(\n item.meteringProfileId,\n path + \".meteringProfileId\"\n ),\n policyKind:\n parsePolicyKind(\n item.policyKind,\n path + \".policyKind\"\n ),\n evidence:\n parseEvidenceList(\n item.evidence,\n path + \".evidence\"\n )\n };\n }\n );\n\n const ids =\n supported.map(\n (entry) =>\n entry.meteringProfileId\n );\n if (\n new Set(ids).size !==\n ids.length\n ) {\n throw new InvalidConfigurationError(\n \"genericBodyMeteringCapabilityProfile.supportedMeteringProfiles must not contain duplicate meteringProfileId values.\"\n );\n }\n\n const spotLink =\n requireRecord(\n record.spotFocusPointLinkage,\n \"genericBodyMeteringCapabilityProfile.spotFocusPointLinkage\", [\"availability\", \"evidence\"]\n );\n\n return {\n schemaVersion:\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"genericBodyMeteringCapabilityProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"genericBodyMeteringCapabilityProfile.profileVersion\"\n ),\n scientificStatus:\n \"approximation\",\n evidence:\n parseEvidenceList(\n record.evidence,\n \"genericBodyMeteringCapabilityProfile.evidence\"\n ),\n supportedMeteringProfiles:\n supported,\n spotFocusPointLinkage: {\n availability:\n parseAvailability(\n spotLink.availability,\n \"genericBodyMeteringCapabilityProfile.spotFocusPointLinkage.availability\"\n ),\n evidence:\n parseEvidenceList(\n spotLink.evidence,\n \"genericBodyMeteringCapabilityProfile.spotFocusPointLinkage.evidence\"\n )\n }\n };\n}\n\n/**\n * Checks whether one engine metering profile is selectable on a generic body.\n *\n * The metering profile stays the single source of its calibration and target\n * policy. They are never copied into equipment capability metadata.\n */\nexport function assessExposureMeteringProfileCompatibility(\n input:\n AssessExposureMeteringProfileCompatibilityInput\n): MeteringCapabilityCompatibilityAssessment {\n requireInputKeys(input, \"assessExposureMeteringProfileCompatibility\", [\"bodyCapabilities\", \"meteringProfile\"]);\n const body =\n parseGenericBodyMeteringCapabilityProfile(\n input.bodyCapabilities\n );\n const metering =\n parseExposureMeteringProfile(\n input.meteringProfile\n );\n\n const declared =\n body.supportedMeteringProfiles.find(\n (entry) =>\n entry.meteringProfileId ===\n metering.profileId\n );\n\n const blockers:\n MeteringCapabilityCompatibilityBlocker[] =\n [];\n\n if (declared === undefined) {\n blockers.push(\n \"metering-profile-unsupported\"\n );\n } else if (\n declared.policyKind !==\n metering.policy.kind\n ) {\n blockers.push(\n \"metering-policy-mismatch\"\n );\n }\n\n if (\n blockers.length >\n new Set(blockers).size\n ) {\n throw new InvalidScientificInputError(\n \"Metering capability compatibility blockers must remain unique.\"\n );\n }\n\n return {\n schemaVersion:\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION,\n status:\n blockers.length === 0\n ? \"compatible\"\n : \"blocked\",\n bodyProfile: {\n profileId: body.profileId,\n profileVersion:\n body.profileVersion\n },\n meteringProfile: {\n profileId:\n metering.profileId,\n policyKind:\n metering.policy.kind\n },\n targetPolicyOwnership:\n \"metering-profile\",\n targetCalibrationDuplicatedInEquipmentProfile:\n false,\n spotFocusPointLinkageAvailability:\n body.spotFocusPointLinkage\n .availability,\n blockers\n };\n}\n"]}
@@ -8,9 +8,9 @@
8
8
  * @see docs/GENERIC_TIER_PRESETS.md for the equations, units, coordinate conventions, known blockers
9
9
  * and support limits.
10
10
  */
11
- import { rejectUnknownFields } from "../core/record-validation.js";
12
11
  import { InvalidConfigurationError } from "../core/configuration-error.js";
13
12
  import { parseEvidenceList } from "../core/evidence-provenance.js";
13
+ import { requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, requireConfigPositiveFinite as requirePositiveFinite, requireConfigPositiveSafeInteger as requirePositiveSafeInteger, requireConfigNonNegativeFinite as requireNonNegativeFinite, parseConfigAvailability as parseAvailability } from "../core/record-validation.js";
14
14
  export const GENERIC_RELEASE_CAPABILITY_SCHEMA_VERSION = "0.1.0";
15
15
  const DRIVE_MODES = new Set([
16
16
  "single",
@@ -22,58 +22,6 @@ const BRACKET_AXES = new Set([
22
22
  "iso",
23
23
  "aperture"
24
24
  ]);
25
- function requireRecord(value, path, allowedKeys) {
26
- if (typeof value !== "object" ||
27
- value === null ||
28
- Array.isArray(value)) {
29
- throw new InvalidConfigurationError(path + " must be an object.");
30
- }
31
- if (allowedKeys !== null)
32
- rejectUnknownFields(value, allowedKeys, path);
33
- return value;
34
- }
35
- function requireNonEmptyString(value, path) {
36
- if (typeof value !== "string" ||
37
- value.trim().length === 0) {
38
- throw new InvalidConfigurationError(path + " must be a non-empty string.");
39
- }
40
- return value.trim();
41
- }
42
- function requirePositiveFinite(value, path) {
43
- if (typeof value !== "number" ||
44
- !Number.isFinite(value) ||
45
- value <= 0) {
46
- throw new InvalidConfigurationError(path +
47
- " must be finite and greater than zero.");
48
- }
49
- return value;
50
- }
51
- function requireNonNegativeFinite(value, path) {
52
- if (typeof value !== "number" ||
53
- !Number.isFinite(value) ||
54
- value < 0) {
55
- throw new InvalidConfigurationError(path +
56
- " must be finite and greater than or equal to zero.");
57
- }
58
- return value;
59
- }
60
- function requirePositiveSafeInteger(value, path) {
61
- if (typeof value !== "number" ||
62
- !Number.isSafeInteger(value) ||
63
- value <= 0) {
64
- throw new InvalidConfigurationError(path +
65
- " must be a positive safe integer.");
66
- }
67
- return value;
68
- }
69
- function parseAvailability(value, path) {
70
- if (value !== "supported" &&
71
- value !== "unsupported" &&
72
- value !== "unknown") {
73
- throw new InvalidConfigurationError(path + " is invalid.");
74
- }
75
- return value;
76
- }
77
25
  function parseFact(value, path, parseValue) {
78
26
  const record = requireRecord(value, path, ["value", "evidence"]);
79
27
  return {