@photivra/engine 2.19.0 → 2.21.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 (242) hide show
  1. package/CHANGELOG.md +289 -1
  2. package/CITATION.cff +1 -1
  3. package/NODE_SUPPORT.md +7 -5
  4. package/README.md +7 -6
  5. package/SECURITY.md +1 -1
  6. package/THIRD_PARTY.md +21 -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/exposure-build-up-stage.d.ts +16 -0
  11. package/dist/capture/exposure-build-up-stage.js +4 -0
  12. package/dist/capture/exposure-build-up-stage.js.map +1 -0
  13. package/dist/capture/native-environment-lean.d.ts +2 -1
  14. package/dist/capture/native-environment-lean.js +42 -78
  15. package/dist/capture/native-environment-lean.js.map +1 -1
  16. package/dist/capture/native-environment-tabulated.js +4 -3
  17. package/dist/capture/native-environment-tabulated.js.map +1 -1
  18. package/dist/capture/native-raw-dng.d.ts +6 -0
  19. package/dist/capture/native-raw-dng.js +16 -2
  20. package/dist/capture/native-raw-dng.js.map +1 -1
  21. package/dist/capture/native-raw.d.ts +3 -2
  22. package/dist/capture/native-raw.js +5 -4
  23. package/dist/capture/native-raw.js.map +1 -1
  24. package/dist/capture/sensor-raw-producer.d.ts +4 -1
  25. package/dist/capture/sensor-raw-producer.js +15 -8
  26. package/dist/capture/sensor-raw-producer.js.map +1 -1
  27. package/dist/core/shared-helpers.d.ts +2 -0
  28. package/dist/core/shared-helpers.js +4 -0
  29. package/dist/core/shared-helpers.js.map +1 -1
  30. package/dist/core/version.d.ts +1 -1
  31. package/dist/core/version.js +1 -1
  32. package/dist/core/version.js.map +1 -1
  33. package/dist/equipment/generic-lens-catalogue.d.ts +11 -4
  34. package/dist/equipment/generic-lens-catalogue.js +49 -7
  35. package/dist/equipment/generic-lens-catalogue.js.map +1 -1
  36. package/dist/equipment/generic-tier-assets.d.ts +32 -0
  37. package/dist/equipment/generic-tier-assets.js +18 -14
  38. package/dist/equipment/generic-tier-assets.js.map +1 -1
  39. package/dist/equipment/generic-tier-presets.js +2 -3
  40. package/dist/equipment/generic-tier-presets.js.map +1 -1
  41. package/dist/equipment/sensor-profile-body.d.ts +78 -0
  42. package/dist/equipment/sensor-profile-body.js +77 -0
  43. package/dist/equipment/sensor-profile-body.js.map +1 -0
  44. package/dist/equipment/sensor-profiles.d.ts +8 -0
  45. package/dist/equipment/sensor-profiles.js +82 -0
  46. package/dist/equipment/sensor-profiles.js.map +1 -0
  47. package/dist/facade/catalogue-lens-signal.d.ts +2 -2
  48. package/dist/facade/catalogue-lens-signal.js +58 -71
  49. package/dist/facade/catalogue-lens-signal.js.map +1 -1
  50. package/dist/facade/chart-radiance-batch.js +2 -1
  51. package/dist/facade/chart-radiance-batch.js.map +1 -1
  52. package/dist/facade/defocus-image-space-provider.d.ts +7 -0
  53. package/dist/facade/defocus-image-space-provider.js +64 -76
  54. package/dist/facade/defocus-image-space-provider.js.map +1 -1
  55. package/dist/facade/display-view-gpu-session.js +2 -0
  56. package/dist/facade/display-view-gpu-session.js.map +1 -1
  57. package/dist/facade/display-view-gpu.d.ts +13 -5
  58. package/dist/facade/display-view-gpu.js +4 -4
  59. package/dist/facade/display-view-gpu.js.map +1 -1
  60. package/dist/facade/display-view-lens-signal.d.ts +1 -1
  61. package/dist/facade/display-view-lens-signal.js +30 -26
  62. package/dist/facade/display-view-lens-signal.js.map +1 -1
  63. package/dist/facade/display-view.d.ts +3 -1
  64. package/dist/facade/display-view.js +6 -24
  65. package/dist/facade/display-view.js.map +1 -1
  66. package/dist/facade/expected-signal-setup.d.ts +3 -1
  67. package/dist/facade/expected-signal-setup.js +1 -1
  68. package/dist/facade/expected-signal-setup.js.map +1 -1
  69. package/dist/facade/expected-signal.d.ts +47 -14
  70. package/dist/facade/expected-signal.js +117 -112
  71. package/dist/facade/expected-signal.js.map +1 -1
  72. package/dist/facade/exposure-build-up.d.ts +70 -0
  73. package/dist/facade/exposure-build-up.js +164 -0
  74. package/dist/facade/exposure-build-up.js.map +1 -0
  75. package/dist/facade/fast-methods.d.ts +50 -0
  76. package/dist/facade/fast-methods.js +58 -0
  77. package/dist/facade/fast-methods.js.map +1 -0
  78. package/dist/facade/fast-resolution.d.ts +12 -0
  79. package/dist/facade/fast-resolution.js +18 -0
  80. package/dist/facade/fast-resolution.js.map +1 -0
  81. package/dist/facade/generic-lens-capture.d.ts +5 -4
  82. package/dist/facade/generic-lens-capture.js +5 -4
  83. package/dist/facade/generic-lens-capture.js.map +1 -1
  84. package/dist/facade/image-plane-enable.d.ts +7 -0
  85. package/dist/facade/image-plane-enable.js +17 -0
  86. package/dist/facade/image-plane-enable.js.map +1 -0
  87. package/dist/facade/image-plane-lattice-data.d.ts +6 -0
  88. package/dist/facade/image-plane-lattice-data.js +10 -0
  89. package/dist/facade/image-plane-lattice-data.js.map +1 -0
  90. package/dist/facade/image-plane-support.d.ts +33 -0
  91. package/dist/facade/image-plane-support.js +11 -0
  92. package/dist/facade/image-plane-support.js.map +1 -0
  93. package/dist/facade/image-plane.d.ts +36 -0
  94. package/dist/facade/image-plane.js +353 -0
  95. package/dist/facade/image-plane.js.map +1 -0
  96. package/dist/facade/mixed-illumination.d.ts +108 -0
  97. package/dist/facade/mixed-illumination.js +174 -0
  98. package/dist/facade/mixed-illumination.js.map +1 -0
  99. package/dist/facade/representative-light-sources.d.ts +72 -0
  100. package/dist/facade/representative-light-sources.js +124 -0
  101. package/dist/facade/representative-light-sources.js.map +1 -0
  102. package/dist/facade/scene-radiance.d.ts +129 -4
  103. package/dist/facade/scene-radiance.js +48 -13
  104. package/dist/facade/scene-radiance.js.map +1 -1
  105. package/dist/facade/simulate-capture.d.ts +88 -19
  106. package/dist/facade/simulate-capture.js +374 -145
  107. package/dist/facade/simulate-capture.js.map +1 -1
  108. package/dist/facade/simulate-display-view.d.ts +3 -2
  109. package/dist/facade/simulate-display-view.js +36 -18
  110. package/dist/facade/simulate-display-view.js.map +1 -1
  111. package/dist/gpu/chart-composite-gpu.d.ts +13 -1
  112. package/dist/gpu/chart-composite-gpu.js +48 -9
  113. package/dist/gpu/chart-composite-gpu.js.map +1 -1
  114. package/dist/gpu/chart-radiance-gpu.js +4 -30
  115. package/dist/gpu/chart-radiance-gpu.js.map +1 -1
  116. package/dist/gpu/display-view-composite-material-module.d.ts +10 -4
  117. package/dist/gpu/display-view-composite-material-module.js +39 -13
  118. package/dist/gpu/display-view-composite-material-module.js.map +1 -1
  119. package/dist/gpu/display-view-image-material-module.d.ts +86 -0
  120. package/dist/gpu/display-view-image-material-module.js +339 -0
  121. package/dist/gpu/display-view-image-material-module.js.map +1 -0
  122. package/dist/gpu/display-view-image-quality.d.ts +45 -0
  123. package/dist/gpu/display-view-image-quality.js +380 -0
  124. package/dist/gpu/display-view-image-quality.js.map +1 -0
  125. package/dist/gpu/display-view-quality-gpu.d.ts +67 -1
  126. package/dist/gpu/display-view-quality-gpu.js +136 -205
  127. package/dist/gpu/display-view-quality-gpu.js.map +1 -1
  128. package/dist/gpu/display-view-speed-gpu.d.ts +51 -3
  129. package/dist/gpu/display-view-speed-gpu.js +131 -93
  130. package/dist/gpu/display-view-speed-gpu.js.map +1 -1
  131. package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +29 -15
  132. package/dist/gpu/wgsl-display-view-quality-kernel.js +58 -36
  133. package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
  134. package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +21 -6
  135. package/dist/gpu/wgsl-display-view-speed-kernel.js +46 -11
  136. package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
  137. package/dist/gpu/wgsl-exact-sum.d.ts +20 -0
  138. package/dist/gpu/wgsl-exact-sum.js +42 -0
  139. package/dist/gpu/wgsl-exact-sum.js.map +1 -0
  140. package/dist/index.d.ts +18 -3
  141. package/dist/index.js +12 -1
  142. package/dist/index.js.map +1 -1
  143. package/dist/motion/subject-motion.d.ts +66 -0
  144. package/dist/motion/subject-motion.js +52 -0
  145. package/dist/motion/subject-motion.js.map +1 -0
  146. package/dist/optics/aperture-diameter.d.ts +47 -0
  147. package/dist/optics/aperture-diameter.js +50 -0
  148. package/dist/optics/aperture-diameter.js.map +1 -0
  149. package/dist/optics/detail-limit.d.ts +182 -0
  150. package/dist/optics/detail-limit.js +336 -0
  151. package/dist/optics/detail-limit.js.map +1 -0
  152. package/dist/optics/generic-lens-lateral-color.d.ts +83 -0
  153. package/dist/optics/generic-lens-lateral-color.js +77 -0
  154. package/dist/optics/generic-lens-lateral-color.js.map +1 -0
  155. package/dist/optics/generic-lens-psf.d.ts +18 -2
  156. package/dist/optics/generic-lens-psf.js +79 -48
  157. package/dist/optics/generic-lens-psf.js.map +1 -1
  158. package/dist/optics/lens-psf-profile.d.ts +7 -0
  159. package/dist/optics/lens-psf-profile.js +2 -1
  160. package/dist/optics/lens-psf-profile.js.map +1 -1
  161. package/dist/optics/scene-to-sensor-irradiance.d.ts +13 -0
  162. package/dist/optics/scene-to-sensor-irradiance.js +7 -0
  163. package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
  164. package/dist/output/crop-to-match-focal-length.d.ts +62 -0
  165. package/dist/output/crop-to-match-focal-length.js +63 -0
  166. package/dist/output/crop-to-match-focal-length.js.map +1 -0
  167. package/dist/output/developed-lens-corrections.d.ts +19 -5
  168. package/dist/output/developed-lens-corrections.js +30 -11
  169. package/dist/output/developed-lens-corrections.js.map +1 -1
  170. package/dist/output/generic-lens-corrections.d.ts +41 -3
  171. package/dist/output/generic-lens-corrections.js +57 -9
  172. package/dist/output/generic-lens-corrections.js.map +1 -1
  173. package/dist/output/lens-corrections.d.ts +12 -2
  174. package/dist/output/lens-corrections.js +22 -7
  175. package/dist/output/lens-corrections.js.map +1 -1
  176. package/dist/output/print-contrast-reference.js +1 -1
  177. package/dist/output/print-contrast-reference.js.map +1 -1
  178. package/dist/output/print-plan.d.ts +41 -5
  179. package/dist/output/print-plan.js +59 -14
  180. package/dist/output/print-plan.js.map +1 -1
  181. package/dist/output/print-size-blur-noise.d.ts +110 -0
  182. package/dist/output/print-size-blur-noise.js +138 -0
  183. package/dist/output/print-size-blur-noise.js.map +1 -0
  184. package/dist/sensor/binomial-sample.d.ts +3 -0
  185. package/dist/sensor/binomial-sample.js +86 -0
  186. package/dist/sensor/binomial-sample.js.map +1 -0
  187. package/dist/sensor/eqe-electron-rate.js +1 -7
  188. package/dist/sensor/eqe-electron-rate.js.map +1 -1
  189. package/dist/sensor/exposure-window.d.ts +2 -0
  190. package/dist/sensor/exposure-window.js +2 -2
  191. package/dist/sensor/exposure-window.js.map +1 -1
  192. package/dist/sensor/readout-timing.js +2 -23
  193. package/dist/sensor/readout-timing.js.map +1 -1
  194. package/dist/sensor/response-application-compatibility.js +1 -6
  195. package/dist/sensor/response-application-compatibility.js.map +1 -1
  196. package/dist/sensor/responsivity-photocurrent.js +1 -7
  197. package/dist/sensor/responsivity-photocurrent.js.map +1 -1
  198. package/dist/sensor/sensor-characteristics.d.ts +147 -0
  199. package/dist/sensor/sensor-characteristics.js +126 -0
  200. package/dist/sensor/sensor-characteristics.js.map +1 -0
  201. package/dist/sensor/spatial-sample-reduction.js +1 -5
  202. package/dist/sensor/spatial-sample-reduction.js.map +1 -1
  203. package/dist/sensor/spectral-quadrature.js +1 -6
  204. package/dist/sensor/spectral-quadrature.js.map +1 -1
  205. package/dist/sensor/temporal-photo-signal.d.ts +3 -0
  206. package/dist/sensor/temporal-photo-signal.js +5 -2
  207. package/dist/sensor/temporal-photo-signal.js.map +1 -1
  208. package/dist/stabilization/system.d.ts +9 -0
  209. package/dist/stabilization/system.js +5 -6
  210. package/dist/stabilization/system.js.map +1 -1
  211. package/docs/AGENT_GUIDE.md +5 -0
  212. package/docs/API_REFERENCE.md +173 -2
  213. package/docs/QUICK_START.md +213 -6
  214. package/docs/USAGE.md +157 -3
  215. package/docs/api/capture-native-raw-dng.md +6 -0
  216. package/docs/api/core-version.md +1 -1
  217. package/docs/api/equipment-generic-lens-catalogue.md +17 -7
  218. package/docs/api/equipment-sensor-profile-body.md +64 -0
  219. package/docs/api/equipment-sensor-profiles.md +86 -0
  220. package/docs/api/exports.json +357 -2
  221. package/docs/api/facade-display-view-gpu.md +5 -2
  222. package/docs/api/facade-exposure-build-up.md +105 -0
  223. package/docs/api/facade-fast-methods.md +99 -0
  224. package/docs/api/facade-image-plane-enable.md +16 -0
  225. package/docs/api/facade-mixed-illumination.md +67 -0
  226. package/docs/api/facade-representative-light-sources.md +131 -0
  227. package/docs/api/facade-scene-radiance.md +54 -3
  228. package/docs/api/facade-simulate-capture.md +60 -15
  229. package/docs/api/facade-simulate-display-view.md +3 -2
  230. package/docs/api/motion-subject-motion.md +23 -0
  231. package/docs/api/optics-aperture-diameter.md +51 -0
  232. package/docs/api/optics-detail-limit.md +203 -0
  233. package/docs/api/optics-generic-lens-lateral-color.md +79 -0
  234. package/docs/api/output-crop-to-match-focal-length.md +67 -0
  235. package/docs/api/output-developed-lens-corrections.md +10 -1
  236. package/docs/api/output-generic-lens-corrections.md +40 -2
  237. package/docs/api/output-lens-corrections.md +11 -1
  238. package/docs/api/output-print-plan.md +35 -1
  239. package/docs/api/output-print-size-blur-noise.md +115 -0
  240. package/docs/api/sensor-sensor-characteristics.md +105 -0
  241. package/llms.txt +6 -0
  242. package/package.json +1 -1
@@ -3,6 +3,7 @@ import { type SensorRawFrameInput, type SensorRawFrame } from "./sensor-raw-fram
3
3
  import { composeSensorAccumulatedCharge, type ComposeSensorPhotoAccumulatedChargeInput as ComposeSensorAccumulatedChargeInput } from "../sensor/accumulated-charge.js";
4
4
  import { assessSensorPhysicalChargeCapacity, type SensorPhysicalChargeCapacityProfile } from "../sensor/physical-charge-capacity.js";
5
5
  import { simulateSensorChargeRealization, simulateSensorRawCode, type SensorChargeSamplingProfile, type SensorReadoutConversionProfile } from "../sensor/raw-readout.js";
6
+ import type { ExposureBuildUpStage } from "./exposure-build-up-stage.js";
6
7
  import { type SensorFixedPatternNoiseProfile } from "../sensor/fixed-pattern-noise.js";
7
8
  import { type CalculateCaptureExposureWindowsInput, type CaptureExposureWindows } from "../sensor/exposure-window.js";
8
9
  export declare const SENSOR_RAW_PRODUCER_SCHEMA_VERSION: "0.3.0";
@@ -60,7 +61,9 @@ export type NativeRawProducerFrameContext = Omit<SensorRawProducerInput["frame"]
60
61
  export declare function parseNativeRawProducerSite(site: unknown, i: number, frame: NativeRawProducerFrameContext, window?: CaptureExposureWindows["samples"][number]): SensorRawProducerSiteInput;
61
62
  export declare function validateNativeRawReadoutIdentity(s: SensorRawProducerSiteInput, first: SensorRawProducerSiteInput): void;
62
63
  /** The shared per-site pipeline holds all the charge, capacity, random-noise and ADC equations. `i` is the absolute native row-major index. */
63
- export declare function calculateNativeRawSite(s: SensorRawProducerSiteInput, seed: number, i: number): SensorRawProducerResult["sites"][number];
64
+ export declare function calculateNativeRawSite(s: SensorRawProducerSiteInput, seed: number, i: number,
65
+ /** Internal (#534): a build-up fraction's stage, which splits the realized counts down to the fraction and reads with its own stream. */
66
+ b?: ExposureBuildUpStage): SensorRawProducerResult["sites"][number];
64
67
  /** Validates the complete per-site exposure inputs. Charge, noise or RAW codes are never accepted as a shortcut. */
65
68
  export declare function parseSensorRawProducerInput(value: unknown): SensorRawProducerInput;
66
69
  /** Runs accumulated charge → capacity → Poisson noise → read noise and ADC → native sample → immutable frame. */
@@ -9,7 +9,7 @@
9
9
  * limits.
10
10
  */
11
11
  import { requireAllowlistedRecord, requirePublicOpaqueId } from "../core/record-validation.js";
12
- import { parseSensorEqeTemporalPhotoSignal } from "../sensor/temporal-photo-signal.js";
12
+ import { parseSensorEqeTemporalPhotoSignal, PHOTO_SIGNAL_DOWNSTREAM_FALSE_FIELDS, PHOTO_SIGNAL_TRUE_FIELDS } from "../sensor/temporal-photo-signal.js";
13
13
  import { RAW_REFERENCE_MAX_NATIVE_SITES } from "./raw-frame-limits.js";
14
14
  import { approximationResult } from "../core/calculation-result.js";
15
15
  import { InvalidConfigurationError } from "../core/configuration-error.js";
@@ -109,10 +109,8 @@ function exposureEvidence(value, temporalPhoto) {
109
109
  }
110
110
  const common = ["colorSamplingProfileId", "channelId", "site", "bindingId", "stationarityProfileId", "timeReference",
111
111
  "startOffsetSecondsFromOpeningReference", "endOffsetSecondsFromOpeningReference", "localExposureDurationSeconds", "componentEvidence"];
112
- const photoTrue = ["timeStationarityEstablished", "temporalIntegrationApplied", "exposureDurationApplied", "countsAreExpectationValues"];
113
- const photoFalse = ["timeVaryingSignalIntegrated", "multiFrameSequenceIntegrated", "darkChargeIncluded", "otherChargeIncluded",
114
- "physicalFullWellAssessmentAuthorized", "cameraSaturationAssessmentAuthorized", "saturationAssessed", "shotNoiseApplied",
115
- "readNoiseApplied", "adcQuantizationApplied", "rawCodeValueProduced", "integerPhotonCountSampled", "integerElectronCountSampled", "chargeCalculated", "currentCalculated"];
112
+ const photoTrue = ["timeStationarityEstablished", ...PHOTO_SIGNAL_TRUE_FIELDS];
113
+ const photoFalse = ["timeVaryingSignalIntegrated", ...PHOTO_SIGNAL_DOWNSTREAM_FALSE_FIELDS];
116
114
  function chargeInput(value) {
117
115
  const r = fields(value, ["photoSignal", "darkCharge", "additionalChargeComponents", "completenessProfile"]);
118
116
  const temporal = r.photoSignal !== null && typeof r.photoSignal === "object" &&
@@ -233,16 +231,25 @@ export function validateNativeRawReadoutIdentity(s, first) {
233
231
  }
234
232
  }
235
233
  /** The shared per-site pipeline holds all the charge, capacity, random-noise and ADC equations. `i` is the absolute native row-major index. */
236
- export function calculateNativeRawSite(s, seed, i) {
234
+ export function calculateNativeRawSite(s, seed, i,
235
+ /** Internal (#534): a build-up fraction's stage, which splits the realized counts down to the fraction and reads with its own stream. */
236
+ b) {
237
237
  const accumulatedCharge = composeSensorAccumulatedCharge(s.charge);
238
238
  const capacity = assessSensorPhysicalChargeCapacity({ accumulatedCharge: accumulatedCharge.value, capacityProfile: s.capacityProfile,
239
239
  operatingStateId: s.operatingStateId, operatingTemperatureC: s.charge.darkCharge.operatingTemperatureC });
240
240
  const pattern = s.fixedPatternNoise === undefined ? {} : { fixedPatternNoise: s.fixedPatternNoise };
241
- const realization = simulateSensorChargeRealization({ accumulatedCharge: accumulatedCharge.value, samplingProfile: s.samplingProfile,
241
+ let realization = simulateSensorChargeRealization({ accumulatedCharge: accumulatedCharge.value, samplingProfile: s.samplingProfile,
242
242
  seedUint32: deriveNativeSiteStreamSeedUint32(seed, i, NATIVE_SITE_CHARGE_STREAM_ID), ...pattern });
243
+ if (b) {
244
+ const v = realization.value;
245
+ if (v.additionalComponents.length)
246
+ throw new InvalidConfigurationError("An exposure build-up takes photo and dark charge only.");
247
+ b.split(i, v.photoSampledMeanElectronCount, v.darkSampledMeanElectronCount, v.photoRealizedElectronCount, v.darkRealizedElectronCount);
248
+ realization = { ...realization, value: { ...v, photoRealizedElectronCount: b.photo, darkRealizedElectronCount: b.dark, totalRealizedStoredElectronEquivalentCount: b.photo + b.dark + 0 } };
249
+ }
243
250
  const readout = simulateSensorRawCode({ chargeRealization: realization.value, physicalCapacityAssessment: capacity.value,
244
251
  readoutProfile: s.readoutProfile, regimeId: s.regimeId,
245
- readNoiseSeedUint32: deriveNativeSiteStreamSeedUint32(seed, i, NATIVE_SITE_READ_NOISE_STREAM_ID), ...pattern });
252
+ readNoiseSeedUint32: deriveNativeSiteStreamSeedUint32(seed, i, b ? b.read : NATIVE_SITE_READ_NOISE_STREAM_ID), ...pattern });
246
253
  return { accumulatedCharge, capacity, realization, readout };
247
254
  }
248
255
  /** The selected regime's declared INL, which the effective white level needs at saturation. */
@@ -1 +1 @@
1
- {"version":3,"file":"sensor-raw-producer.js","sourceRoot":"","sources":["../../src/capture/sensor-raw-producer.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Produces a sensor RAW frame from per-site exposure inputs, using the existing sensor steps:\n * accumulated charge → capacity → Poisson (shot) noise → read noise and ADC → native sample →\n * immutable frame.\n *\n * Inputs must be complete. Charge, noise or RAW codes cannot be passed in as a shortcut.\n * @see docs/SIMULATED_CAPTURE.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport { requireAllowlistedRecord, requirePublicOpaqueId } from \"../core/record-validation.js\";\n\nimport { parseSensorEqeTemporalPhotoSignal } from \"../sensor/temporal-photo-signal.js\";\nimport { RAW_REFERENCE_MAX_NATIVE_SITES } from \"./raw-frame-limits.js\";\n\nimport { approximationResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { parseEvidenceList } from \"../core/evidence-provenance.js\";\nimport { parseSimulatedCapture } from \"./simulated-capture.js\";\nimport { createSensorRawFrame, type SensorRawFrameInput, type SensorRawFrame } from \"./sensor-raw-frame.js\";\nimport { composeSensorAccumulatedCharge, parseSensorAccumulatedChargeCompletenessProfile, parseSensorAdditionalStoredChargeComponent,\n type ComposeSensorPhotoAccumulatedChargeInput as ComposeSensorAccumulatedChargeInput } from \"../sensor/accumulated-charge.js\";\nimport { assessSensorPhysicalChargeCapacity, parseSensorPhysicalChargeCapacityProfile,\n type SensorPhysicalChargeCapacityProfile } from \"../sensor/physical-charge-capacity.js\";\nimport { simulateSensorChargeRealization, simulateSensorRawCode, parseSensorChargeSamplingProfile,\n parseSensorReadoutConversionProfile, resolveSensorReadoutRegime, type SensorChargeSamplingProfile, type SensorReadoutConversionProfile } from \"../sensor/raw-readout.js\";\nimport { createSensorRawCaptureSample } from \"../sensor/raw-reconstruction.js\";\nimport { parseSensorFixedPatternNoiseProfile, type SensorFixedPatternNoiseProfile } from \"../sensor/fixed-pattern-noise.js\";\nimport { deriveNativeSiteStreamSeedUint32, NATIVE_SITE_CHARGE_STREAM_ID, NATIVE_SITE_READ_NOISE_STREAM_ID } from \"../sensor/stochastic-seed.js\";\nimport { parseSensorColorSamplingProfile } from \"../sensor/color-sampling.js\";\nimport { parseCaptureModeProfile } from \"../sensor/capture-mode.js\";\nimport { parseNativeEffectiveRasterColorSamplingBindingProfile, resolveCaptureModeColorSamplingContributors } from \"../sensor/capture-color-sampling-binding.js\";\nimport { calculateCaptureExposureWindows, type CalculateCaptureExposureWindowsInput, type CaptureExposureWindows } from \"../sensor/exposure-window.js\";\n\nexport const SENSOR_RAW_PRODUCER_SCHEMA_VERSION = \"0.3.0\" as const;\n/**\n * Version of the capture noise model. It fixes the hashed per-site seed schedule and the signed electronic\n * readout behaviour.\n *\n * 0.4.0: exact ADC rounding with ties up, normal-approximation Poisson draws for means of 1e9 and above,\n * optional post-ADC digital gain and INL (integral non-linearity), and optional per-sensor fixed-pattern noise.\n */\nexport const SENSOR_RAW_PRODUCER_NOISE_MODEL = /* @__PURE__ */ Object.freeze({ id: \"photivra-native-raw-noise\", version: \"0.4.0\" } as const);\n/** For each native site: one declared exposure event (EQE photo signal, dark signal, charge completeness) and its readout state. */\nexport interface SensorRawProducerSiteInput {\n charge: ComposeSensorAccumulatedChargeInput;\n samplingProfile: SensorChargeSamplingProfile;\n capacityProfile: SensorPhysicalChargeCapacityProfile;\n operatingStateId: string;\n readoutProfile: SensorReadoutConversionProfile;\n regimeId: string;\n /** Optional fixed-pattern noise (FPN) for this sensor; one profile for the whole frame. Omit it to disable FPN. */\n fixedPatternNoise?: SensorFixedPatternNoiseProfile;\n}\n/** Exposure schedule for the full sensor. The producer owns the sampling coordinates. */\nexport type SensorRawProducerExposureWindowInput = Omit<CalculateCaptureExposureWindowsInput,\n \"nativeRaster\" | \"activeCaptureRect\" | \"samplePointsNative\">;\n/** Input for one bounded frame. It is never a conversion from separate RGB pixels. */\nexport interface SensorRawProducerInput {\n frame: Omit<SensorRawFrameInput, \"samples\">;\n sites: readonly SensorRawProducerSiteInput[];\n /** If omitted, every event uses the existing global window 0..shutterSeconds. */\n exposureWindow?: SensorRawProducerExposureWindowInput;\n}\n/** Codes produced by the engine, with per-step diagnostics. The upstream radiance and response are as declared, not verified. */\nexport interface SensorRawProducerResult {\n schemaVersion: typeof SENSOR_RAW_PRODUCER_SCHEMA_VERSION;\n codeProducer: \"engine-charge-capacity-noise-adc\";\n upstreamOrigin: \"declared-eqe-and-dark-exposure-results\";\n upstreamRadiometryVerified: false;\n seedSchedule: \"murmur3-capture-seed-native-index-stream-v2\";\n frame: SensorRawFrame;\n localExposureWindows?: CalculationResult<CaptureExposureWindows>;\n sites: readonly {\n accumulatedCharge: ReturnType<typeof composeSensorAccumulatedCharge>;\n capacity: ReturnType<typeof assessSensorPhysicalChargeCapacity>;\n realization: ReturnType<typeof simulateSensorChargeRealization>;\n readout: ReturnType<typeof simulateSensorRawCode>;\n }[];\n}\nfunction fields(value: unknown, allowed: readonly string[]): Record<string, unknown> {\n return requireAllowlistedRecord(value, allowed, \"Invalid sensor RAW producer fields.\");\n}\nfunction publicId(value: unknown): string {\n return requirePublicOpaqueId(value, \"Expected public producer identity.\");\n}\nconst KEY_RECURSE = 0, KEY_IDENTITY = 1, KEY_IDENTITY_LIST = 2;\n/** Bounded cache of how the identity check classifies each property name (it depends only on the name). */\nconst IDENTITY_KEY_KINDS = new Map<string, number>();\n/** Bounded cache of strings already known to be valid public IDs (validity depends only on the string). */\nconst VALID_PUBLIC_IDS = new Set<string>();\nconst IDENTITY_WALK_MEMO_LIMIT = 4096;\nfunction identityKeyKind(key: string): number {\n // Array indices and other names ending in a digit match neither suffix.\n const last = key.charCodeAt(key.length - 1);\n if (last >= 48 && last <= 57) return KEY_RECURSE;\n let kind = IDENTITY_KEY_KINDS.get(key);\n if (kind === undefined) {\n kind = /(?:Id|Version)$/.test(key) ? KEY_IDENTITY : /Ids$/.test(key) ? KEY_IDENTITY_LIST : KEY_RECURSE;\n if (IDENTITY_KEY_KINDS.size < IDENTITY_WALK_MEMO_LIMIT) IDENTITY_KEY_KINDS.set(key, kind);\n }\n return kind;\n}\nfunction memoizedPublicId(value: unknown): void {\n if (typeof value === \"string\" && VALID_PUBLIC_IDS.has(value)) return;\n publicId(value);\n if (VALID_PUBLIC_IDS.size < IDENTITY_WALK_MEMO_LIMIT) VALID_PUBLIC_IDS.add(value as string);\n}\n/**\n * At any depth, every property whose name ends in Id or Version must hold a public ID, and every property\n * ending in Ids a bounded dense list of them. Order, keys and errors are the same as the earlier\n * Object.entries walk. Key classification and already-valid IDs are cached, because each depends only on\n * its string.\n */\nfunction publicIdentities(value: unknown): void {\n if (value === null || typeof value !== \"object\") return;\n const record = value as Record<string, unknown>, keys = Object.keys(record);\n for (let index = 0; index < keys.length; index++) {\n const key = keys[index]!, kind = identityKeyKind(key), child = record[key];\n if (kind === KEY_IDENTITY) memoizedPublicId(child);\n else if (kind === KEY_IDENTITY_LIST) dense(child, 256).forEach(memoizedPublicId);\n else if (child !== null && typeof child === \"object\") publicIdentities(child);\n }\n}\nfunction dense(value: unknown, maximum: number): unknown[] {\n if (!Array.isArray(value) || value.length > maximum || Array.from({ length: value.length }, (_, i) => i in value).includes(false)) {\n throw new InvalidConfigurationError(\"Expected bounded dense producer array.\");\n }\n return value;\n}\nfunction optionalEvidence(value: unknown): ReturnType<typeof parseEvidenceList> {\n return dense(value, 256).length === 0 ? [] : parseEvidenceList(value, \"optionalExposureEvidence\");\n}\nfunction exposureEvidence(value: unknown, temporalPhoto?: Record<string, unknown>): ComposeSensorAccumulatedChargeInput[\"photoSignal\"][\"componentEvidence\"] {\n if (temporalPhoto !== undefined) return parseSensorEqeTemporalPhotoSignal({ ...temporalPhoto, componentEvidence: value }).componentEvidence;\n const r = fields(value, [\"stationarity\", \"exposureBinding\"]);\n const b = fields(r.exposureBinding, [\"binding\", \"colorSamplingProfile\", \"nominalExposureDuration\", \"openingBoundary\", \"closingBoundary\"]);\n return { stationarity: parseEvidenceList(r.stationarity, \"stationarity\"), exposureBinding: {\n binding: parseEvidenceList(b.binding, \"binding\"), colorSamplingProfile: parseEvidenceList(b.colorSamplingProfile, \"colorSamplingProfile\"),\n nominalExposureDuration: parseEvidenceList(b.nominalExposureDuration, \"nominalExposureDuration\"),\n openingBoundary: optionalEvidence(b.openingBoundary), closingBoundary: optionalEvidence(b.closingBoundary) } };\n}\nconst common = [\"colorSamplingProfileId\", \"channelId\", \"site\", \"bindingId\", \"stationarityProfileId\", \"timeReference\",\n \"startOffsetSecondsFromOpeningReference\", \"endOffsetSecondsFromOpeningReference\", \"localExposureDurationSeconds\", \"componentEvidence\"];\nconst photoTrue = [\"timeStationarityEstablished\", \"temporalIntegrationApplied\", \"exposureDurationApplied\", \"countsAreExpectationValues\"];\nconst photoFalse = [\"timeVaryingSignalIntegrated\", \"multiFrameSequenceIntegrated\", \"darkChargeIncluded\", \"otherChargeIncluded\",\n \"physicalFullWellAssessmentAuthorized\", \"cameraSaturationAssessmentAuthorized\", \"saturationAssessed\", \"shotNoiseApplied\",\n \"readNoiseApplied\", \"adcQuantizationApplied\", \"rawCodeValueProduced\", \"integerPhotonCountSampled\", \"integerElectronCountSampled\", \"chargeCalculated\", \"currentCalculated\"];\nfunction chargeInput(value: unknown): ComposeSensorAccumulatedChargeInput {\n const r = fields(value, [\"photoSignal\", \"darkCharge\", \"additionalChargeComponents\", \"completenessProfile\"]);\n const temporal = r.photoSignal !== null && typeof r.photoSignal === \"object\" &&\n (r.photoSignal as Record<string, unknown>).kind === \"eqe-temporal-photo-signal\";\n const p = temporal ? parseSensorEqeTemporalPhotoSignal(r.photoSignal) as unknown as Record<string, unknown> : fields(r.photoSignal, [...common, ...photoTrue, ...photoFalse, \"kind\", \"stationarityStatus\", \"integrationMethod\",\n \"accumulatedSignalCompleteness\", \"incidentPhotonRatePerSecond\", \"expectedGeneratedElectronRatePerSecond\", \"expectedIncidentPhotonCount\", \"expectedGeneratedElectronCount\"]);\n const darkFalse = [\"integerDarkElectronCountSampled\", \"darkShotNoiseApplied\", \"darkCurrentCompensationApplied\", \"photoSignalIncluded\",\n \"otherChargeIncluded\", \"physicalFullWellAssessmentAuthorized\", \"saturationAssessed\"];\n const d = fields(r.darkCharge, [...common, ...darkFalse, \"darkCurrentProfileId\", \"operatingTemperatureC\", \"temperatureModel\",\n \"temperatureInterpolationUsed\", \"temporalIntegrationId\", \"darkCurrentElectronsPerSecond\", \"expectedDarkElectronCount\", \"countMeaning\", \"expectationValueOnly\", \"spatialDarkCurrentNonuniformityModeled\"]);\n if ((!temporal && (p.kind !== \"eqe-expected-counts\" || p.integrationMethod !== \"constant-rate-times-local-exposure-duration\" ||\n p.accumulatedSignalCompleteness !== \"photo-signal-only\" || (p.stationarityStatus !== \"established\" && p.stationarityStatus !== \"approximation\") ||\n photoTrue.some((k) => p[k] !== true) || photoFalse.some((k) => p[k] !== false))) || darkFalse.some((k) => d[k] !== false) ||\n d.expectationValueOnly !== true || d.countMeaning !== \"expected-thermally-generated-electrons\" ||\n typeof d.spatialDarkCurrentNonuniformityModeled !== \"boolean\" || typeof d.temperatureInterpolationUsed !== \"boolean\" ||\n (d.temperatureModel !== \"fixed-reference-temperature\" && d.temperatureModel !== \"piecewise-linear-temperature-table\" &&\n d.temperatureModel !== \"log-linear-temperature-table\")) {\n throw new InvalidConfigurationError(\"Producer requires untreated EQE/dark exposure expectations, not sampled, clipped or A/W charge.\");\n }\n if (d.temperatureModel === \"fixed-reference-temperature\" && d.temperatureInterpolationUsed !== false) {\n throw new InvalidConfigurationError(\"Fixed-temperature dark result cannot claim temperature interpolation.\");\n }\n for (const record of [p, d]) {\n for (const k of [\"colorSamplingProfileId\", \"channelId\", \"bindingId\", temporal ? \"temporalIntegrationId\" : \"stationarityProfileId\"]) publicId(record[k]);\n fields(record.site, [\"x\", \"y\"]);\n if (record.timeReference !== \"first-opening-boundary-phase\") throw new InvalidConfigurationError(\"Unsupported producer time origin.\");\n }\n publicId(d.darkCurrentProfileId);\n for (const [record, keys] of [[p, [\"incidentPhotonRatePerSecond\", \"expectedGeneratedElectronRatePerSecond\", \"expectedIncidentPhotonCount\", \"expectedGeneratedElectronCount\"]],\n [d, [\"darkCurrentElectronsPerSecond\", \"expectedDarkElectronCount\"]]] as const) {\n for (const k of keys) if (!(temporal && record === p && k.endsWith(\"RatePerSecond\")) && (typeof record[k] !== \"number\" || !Number.isFinite(record[k]) || record[k] < 0)) throw new InvalidConfigurationError(\"Invalid expected rates/counts.\");\n }\n const duration = p.localExposureDurationSeconds;\n if (typeof duration !== \"number\" || !Number.isFinite(duration) || duration <= 0 ||\n (!temporal && (p.expectedIncidentPhotonCount !== (p.incidentPhotonRatePerSecond as number)*duration ||\n p.expectedGeneratedElectronCount !== (p.expectedGeneratedElectronRatePerSecond as number)*duration)) ||\n d.expectedDarkElectronCount !== (d.darkCurrentElectronsPerSecond as number)*duration ||\n (p.expectedGeneratedElectronCount as number) > (p.expectedIncidentPhotonCount as number)) {\n throw new InvalidConfigurationError(\"Exposure expectations must match their exact temporal integral or constant-rate products and EQE domain.\");\n }\n const e = fields(d.componentEvidence, [\"darkCurrent\", \"siteApproximation\", \"exposure\"]);\n const charge = { photoSignal: { ...p, componentEvidence: exposureEvidence(p.componentEvidence, temporal ? p : undefined) },\n darkCharge: { ...d, componentEvidence: { darkCurrent: parseEvidenceList(e.darkCurrent, \"darkCurrent\"),\n siteApproximation: optionalEvidence(e.siteApproximation), exposure: exposureEvidence(e.exposure, temporal ? p : undefined) } },\n completenessProfile: parseSensorAccumulatedChargeCompletenessProfile(r.completenessProfile),\n ...(r.additionalChargeComponents === undefined ? {} : { additionalChargeComponents:\n dense(r.additionalChargeComponents, 32).map(parseSensorAdditionalStoredChargeComponent) }) } as unknown as ComposeSensorAccumulatedChargeInput;\n // The existing charge composition checks that photo, dark, additional and completeness events agree exactly.\n composeSensorAccumulatedCharge(charge);\n return charge;\n}\nfunction localWindows(frame: SensorRawProducerInput[\"frame\"], value: unknown): CalculationResult<CaptureExposureWindows> {\n const r = fields(value, [\"shutterMechanism\", \"nominalExposureDurationSeconds\", \"opening\", \"closing\"]);\n fields(r.nominalExposureDurationSeconds, [\"value\", \"unit\", \"evidence\"]);\n for (const boundary of [r.opening, r.closing]) {\n const b = fields(boundary, [\"kind\", \"directionNative\", \"traversalDurationSeconds\"]);\n if (b.directionNative !== undefined) fields(b.directionNative, [\"value\", \"evidence\"]);\n if (b.traversalDurationSeconds !== undefined) fields(b.traversalDurationSeconds, [\"value\", \"unit\", \"evidence\"]);\n }\n const native = frame.capture.geometry.nativeRaster;\n const timing = calculateCaptureExposureWindows({\n ...r as unknown as SensorRawProducerExposureWindowInput,\n nativeRaster: native,\n samplePointsNative: Array.from({ length: native.pixelWidth*native.pixelHeight }, (_, i) => ({\n x: i%native.pixelWidth+0.5, y: Math.floor(i/native.pixelWidth)+0.5\n }))\n });\n if (timing.value.nominalExposureDurationSeconds.value !== frame.capture.exposure.shutterSeconds) {\n throw new InvalidConfigurationError(\"Exposure schedule nominal duration differs from committed capture.\");\n }\n return timing;\n}\nfunction sourceBoundary(schedule: CaptureExposureWindows[\"opening\"][\"schedule\"]): SensorRawProducerExposureWindowInput[\"opening\"] {\n return schedule.kind === \"simultaneous\" ? { kind: \"simultaneous\" } : {\n kind: \"uniform-linear-native-scan\", directionNative: schedule.directionNative,\n traversalDurationSeconds: schedule.traversalDurationSeconds\n };\n}\n/** Internal: per-site validation shared by the reference path and bounded packed execution. */\nexport type NativeRawProducerFrameContext = Omit<SensorRawProducerInput[\"frame\"], \"capture\"> & {\n capture: Pick<SensorRawProducerInput[\"frame\"][\"capture\"], \"geometry\" | \"exposure\" | \"noise\" | \"focus\" | \"sceneStateId\" | \"sceneTimeSeconds\">;\n};\nexport function parseNativeRawProducerSite(site: unknown, i: number, frame: NativeRawProducerFrameContext,\n window?: CaptureExposureWindows[\"samples\"][number]): SensorRawProducerSiteInput {\n const native = frame.capture.geometry.nativeRaster;\n const s = fields(site, [\"charge\", \"samplingProfile\", \"capacityProfile\", \"operatingStateId\", \"readoutProfile\", \"regimeId\", \"fixedPatternNoise\"]);\n const charge = chargeInput(s.charge), p = charge.photoSignal;\n const contributors = resolveCaptureModeColorSamplingContributors({ nativeRaster: native, captureModeProfile: frame.captureModeProfile,\n modeId: frame.modeId, colorSamplingProfile: frame.colorSamplingProfile, bindingProfile: frame.bindingProfile,\n modeSampleIndexFullFrame: { x: i%native.pixelWidth, y: Math.floor(i/native.pixelWidth) } });\n\n if (contributors.totalContributorSites !== 1 || contributors.channelComposition.kind !== \"single-channel\" ||\n p.colorSamplingProfileId !== frame.colorSamplingProfile.profileId || p.channelId !== contributors.channelComposition.channelId ||\n p.site.x !== contributors.colorSamplingSiteRect.x || p.site.y !== contributors.colorSamplingSiteRect.y ||\n p.bindingId !== frame.bindingProfile.bindingId || p.startOffsetSecondsFromOpeningReference !== (window?.startOffsetSecondsFromOpeningReference ?? 0) ||\n p.endOffsetSecondsFromOpeningReference !== (window?.endOffsetSecondsFromOpeningReference ?? frame.capture.exposure.shutterSeconds) ||\n p.localExposureDurationSeconds !== (window?.localExposureDurationSeconds ?? frame.capture.exposure.shutterSeconds)) {\n throw new InvalidConfigurationError(\"Charge site/channel/binding/local exposure differs from committed capture.\");\n }\n const readoutProfile = parseSensorReadoutConversionProfile(s.readoutProfile);\n const isoGain = readoutProfile.regimes.find((regime) => regime.regimeId === s.regimeId)?.exposureIndexGain;\n if (isoGain !== undefined && isoGain.exposureIndex !== frame.capture.exposure.iso) {\n throw new InvalidConfigurationError(\"Readout regime ISO gain differs from the committed capture ISO.\");\n }\n return { charge, samplingProfile: parseSensorChargeSamplingProfile(s.samplingProfile), capacityProfile: parseSensorPhysicalChargeCapacityProfile(s.capacityProfile),\n operatingStateId: publicId(s.operatingStateId), readoutProfile, regimeId: publicId(s.regimeId),\n ...(s.fixedPatternNoise === undefined ? {} : { fixedPatternNoise: parseSensorFixedPatternNoiseProfile(s.fixedPatternNoise) }) };\n}\nexport function validateNativeRawReadoutIdentity(s: SensorRawProducerSiteInput, first: SensorRawProducerSiteInput): void {\n publicIdentities(s);\n const readout = resolveSensorReadoutRegime({ profile: s.readoutProfile, regimeId: s.regimeId });\n if (s.readoutProfile.profileId !== first.readoutProfile.profileId || s.regimeId !== first.regimeId ||\n readout.regime.adc.bitDepth > 16 || readout.regime.adc.digitalSaturationCode <= readout.regime.adc.blackLevelCode ||\n s.readoutProfile.colorSamplingProfileId !== s.charge.photoSignal.colorSamplingProfileId ||\n s.readoutProfile.channelId !== s.charge.photoSignal.channelId || s.samplingProfile.completenessProfileId !== s.charge.completenessProfile.profileId ||\n s.fixedPatternNoise?.profileId !== first.fixedPatternNoise?.profileId ||\n s.fixedPatternNoise?.sensorInstanceSeedUint32 !== first.fixedPatternNoise?.sensorInstanceSeedUint32) {\n throw new InvalidConfigurationError(\"Frame requires one readout identity/regime, one fixed-pattern identity and a positive uint16 RAW code span.\");\n }\n}\n/** The shared per-site pipeline holds all the charge, capacity, random-noise and ADC equations. `i` is the absolute native row-major index. */\nexport function calculateNativeRawSite(s: SensorRawProducerSiteInput, seed: number, i: number): SensorRawProducerResult[\"sites\"][number] {\n const accumulatedCharge = composeSensorAccumulatedCharge(s.charge);\n const capacity = assessSensorPhysicalChargeCapacity({ accumulatedCharge: accumulatedCharge.value, capacityProfile: s.capacityProfile,\n operatingStateId: s.operatingStateId, operatingTemperatureC: s.charge.darkCharge.operatingTemperatureC });\n const pattern = s.fixedPatternNoise === undefined ? {} : { fixedPatternNoise: s.fixedPatternNoise };\n const realization = simulateSensorChargeRealization({ accumulatedCharge: accumulatedCharge.value, samplingProfile: s.samplingProfile,\n seedUint32: deriveNativeSiteStreamSeedUint32(seed, i, NATIVE_SITE_CHARGE_STREAM_ID), ...pattern });\n const readout = simulateSensorRawCode({ chargeRealization: realization.value, physicalCapacityAssessment: capacity.value,\n readoutProfile: s.readoutProfile, regimeId: s.regimeId,\n readNoiseSeedUint32: deriveNativeSiteStreamSeedUint32(seed, i, NATIVE_SITE_READ_NOISE_STREAM_ID), ...pattern });\n return { accumulatedCharge, capacity, realization, readout };\n}\n/** The selected regime's declared INL, which the effective white level needs at saturation. */\nfunction regimeInl(site: SensorRawProducerSiteInput): { adcIntegralNonLinearity?: NonNullable<SensorReadoutConversionProfile[\"regimes\"][number][\"adc\"][\"integralNonLinearity\"]> } {\n const inl = site.readoutProfile.regimes.find((r) => r.regimeId === site.regimeId)?.adc.integralNonLinearity;\n return inl === undefined ? {} : { adcIntegralNonLinearity: inl };\n}\n/** Validates the complete per-site exposure inputs. Charge, noise or RAW codes are never accepted as a shortcut. */\nexport function parseSensorRawProducerInput(value: unknown): SensorRawProducerInput {\n const r = fields(value, [\"frame\", \"sites\", \"exposureWindow\"]), f = fields(r.frame, [\"frameId\", \"capture\", \"modeId\", \"captureModeProfile\", \"colorSamplingProfile\", \"bindingProfile\", \"containerBitDepth\"]);\n const capture = parseSimulatedCapture(f.capture), native = capture.geometry.nativeRaster, count = native.pixelWidth*native.pixelHeight;\n const sites = dense(r.sites, RAW_REFERENCE_MAX_NATIVE_SITES);\n const frame = { frameId: publicId(f.frameId), capture, modeId: publicId(f.modeId), containerBitDepth: 16 as const,\n captureModeProfile: parseCaptureModeProfile(f.captureModeProfile), colorSamplingProfile: parseSensorColorSamplingProfile(f.colorSamplingProfile),\n bindingProfile: parseNativeEffectiveRasterColorSamplingBindingProfile(f.bindingProfile) };\n const mode = frame.captureModeProfile.modes.find((m) => m.modeId === frame.modeId);\n if (f.containerBitDepth !== 16 || count > RAW_REFERENCE_MAX_NATIVE_SITES || sites.length !== count ||\n capture.noise.model.id !== SENSOR_RAW_PRODUCER_NOISE_MODEL.id || capture.noise.model.version !== SENSOR_RAW_PRODUCER_NOISE_MODEL.version ||\n frame.colorSamplingProfile.layout.kind !== \"periodic-mosaic\" || !mode || mode.acquisition.kind !== \"single-frame\" ||\n mode.perFrameSampling.kind !== \"native-effective-raster\" || (mode.reconstructionStages?.length ?? 0) !== 0) {\n throw new InvalidConfigurationError(\"Producer requires exact noise identity and bounded single-frame native CFA coverage.\");\n }\n const timing = r.exposureWindow === undefined ? undefined : localWindows(frame, r.exposureWindow);\n const parsed = sites.map((site, i) => parseNativeRawProducerSite(site, i, frame, timing?.value.samples[i]));\n for (const site of parsed) validateNativeRawReadoutIdentity(site, parsed[0]!);\n publicIdentities(frame);\n return { frame, sites: parsed, ...(timing === undefined ? {} : { exposureWindow: {\n shutterMechanism: timing.value.shutterMechanism,\n nominalExposureDurationSeconds: timing.value.nominalExposureDurationSeconds,\n opening: sourceBoundary(timing.value.opening.schedule), closing: sourceBoundary(timing.value.closing.schedule)\n } }) };\n}\n/** Runs accumulated charge → capacity → Poisson noise → read noise and ADC → native sample → immutable frame. */\nexport function simulateSensorRawFrame(input: SensorRawProducerInput): CalculationResult<SensorRawProducerResult> {\n const v = parseSensorRawProducerInput(input), seed = v.frame.capture.noise.seedUint32;\n const sites = v.sites.map((s, i) => calculateNativeRawSite(s, seed, i));\n const native = v.frame.capture.geometry.nativeRaster;\n const samples = sites.map((s, i) => createSensorRawCaptureSample({ rawCode: s.readout.value,\n ...regimeInl(v.sites[i]!),\n contributors: resolveCaptureModeColorSamplingContributors({ nativeRaster: native, captureModeProfile: v.frame.captureModeProfile,\n modeId: v.frame.modeId, colorSamplingProfile: v.frame.colorSamplingProfile, bindingProfile: v.frame.bindingProfile,\n modeSampleIndexFullFrame: { x: i%native.pixelWidth, y: Math.floor(i/native.pixelWidth) } }) }));\n return approximationResult({ schemaVersion: SENSOR_RAW_PRODUCER_SCHEMA_VERSION, codeProducer: \"engine-charge-capacity-noise-adc\",\n upstreamOrigin: \"declared-eqe-and-dark-exposure-results\", upstreamRadiometryVerified: false,\n seedSchedule: \"murmur3-capture-seed-native-index-stream-v2\", frame: createSensorRawFrame({ ...v.frame, samples }), sites,\n ...(v.exposureWindow === undefined ? {} : { localExposureWindows: localWindows(v.frame, v.exposureWindow) }) },\n \"native-sensor-raw-frame-producer\", SENSOR_RAW_PRODUCER_SCHEMA_VERSION, [\n \"Untreated EQE/dark exposure results and completeness evidence are upstream declarations; source radiometry is not independently verified\",\n \"Native row-major site seeds are MurmurHash3_x86_32 of (capture seed, absolute native index, stream 0 charge / 1 read noise); deterministic and non-cryptographic\",\n \"Existing scalar capacity/noise/readout approximations retain distinct physical/pre-ADC/digital saturation diagnostics; no blooming\",\n \"Optional fixed-pattern noise is deterministic per sensor instance (its own seed and absolute colour-sampling site), independent of the capture seed\",\n \"Stationarity applies separately to every exact local window; no time-varying radiance integration, multi-frame acquisition, RGB-to-RAW conversion or production-stage activation\",\n \"Stored capture float planes remain independent; same-RAW export must use the returned frame's reconstruction handoff\"]);\n}\n"]}
1
+ {"version":3,"file":"sensor-raw-producer.js","sourceRoot":"","sources":["../../src/capture/sensor-raw-producer.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Produces a sensor RAW frame from per-site exposure inputs, using the existing sensor steps:\n * accumulated charge → capacity → Poisson (shot) noise → read noise and ADC → native sample →\n * immutable frame.\n *\n * Inputs must be complete. Charge, noise or RAW codes cannot be passed in as a shortcut.\n * @see docs/SIMULATED_CAPTURE.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport { requireAllowlistedRecord, requirePublicOpaqueId } from \"../core/record-validation.js\";\n\nimport { parseSensorEqeTemporalPhotoSignal, PHOTO_SIGNAL_DOWNSTREAM_FALSE_FIELDS, PHOTO_SIGNAL_TRUE_FIELDS } from \"../sensor/temporal-photo-signal.js\";\nimport { RAW_REFERENCE_MAX_NATIVE_SITES } from \"./raw-frame-limits.js\";\n\nimport { approximationResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { parseEvidenceList } from \"../core/evidence-provenance.js\";\nimport { parseSimulatedCapture } from \"./simulated-capture.js\";\nimport { createSensorRawFrame, type SensorRawFrameInput, type SensorRawFrame } from \"./sensor-raw-frame.js\";\nimport { composeSensorAccumulatedCharge, parseSensorAccumulatedChargeCompletenessProfile, parseSensorAdditionalStoredChargeComponent,\n type ComposeSensorPhotoAccumulatedChargeInput as ComposeSensorAccumulatedChargeInput } from \"../sensor/accumulated-charge.js\";\nimport { assessSensorPhysicalChargeCapacity, parseSensorPhysicalChargeCapacityProfile,\n type SensorPhysicalChargeCapacityProfile } from \"../sensor/physical-charge-capacity.js\";\nimport { simulateSensorChargeRealization, simulateSensorRawCode, parseSensorChargeSamplingProfile,\n parseSensorReadoutConversionProfile, resolveSensorReadoutRegime, type SensorChargeSamplingProfile, type SensorReadoutConversionProfile } from \"../sensor/raw-readout.js\";\nimport { createSensorRawCaptureSample } from \"../sensor/raw-reconstruction.js\";\nimport type { ExposureBuildUpStage } from \"./exposure-build-up-stage.js\";\nimport { parseSensorFixedPatternNoiseProfile, type SensorFixedPatternNoiseProfile } from \"../sensor/fixed-pattern-noise.js\";\nimport { deriveNativeSiteStreamSeedUint32, NATIVE_SITE_CHARGE_STREAM_ID, NATIVE_SITE_READ_NOISE_STREAM_ID } from \"../sensor/stochastic-seed.js\";\nimport { parseSensorColorSamplingProfile } from \"../sensor/color-sampling.js\";\nimport { parseCaptureModeProfile } from \"../sensor/capture-mode.js\";\nimport { parseNativeEffectiveRasterColorSamplingBindingProfile, resolveCaptureModeColorSamplingContributors } from \"../sensor/capture-color-sampling-binding.js\";\nimport { calculateCaptureExposureWindows, type CalculateCaptureExposureWindowsInput, type CaptureExposureWindows } from \"../sensor/exposure-window.js\";\n\nexport const SENSOR_RAW_PRODUCER_SCHEMA_VERSION = \"0.3.0\" as const;\n/**\n * Version of the capture noise model. It fixes the hashed per-site seed schedule and the signed electronic\n * readout behaviour.\n *\n * 0.4.0: exact ADC rounding with ties up, normal-approximation Poisson draws for means of 1e9 and above,\n * optional post-ADC digital gain and INL (integral non-linearity), and optional per-sensor fixed-pattern noise.\n */\nexport const SENSOR_RAW_PRODUCER_NOISE_MODEL = /* @__PURE__ */ Object.freeze({ id: \"photivra-native-raw-noise\", version: \"0.4.0\" } as const);\n/** For each native site: one declared exposure event (EQE photo signal, dark signal, charge completeness) and its readout state. */\nexport interface SensorRawProducerSiteInput {\n charge: ComposeSensorAccumulatedChargeInput;\n samplingProfile: SensorChargeSamplingProfile;\n capacityProfile: SensorPhysicalChargeCapacityProfile;\n operatingStateId: string;\n readoutProfile: SensorReadoutConversionProfile;\n regimeId: string;\n /** Optional fixed-pattern noise (FPN) for this sensor; one profile for the whole frame. Omit it to disable FPN. */\n fixedPatternNoise?: SensorFixedPatternNoiseProfile;\n}\n/** Exposure schedule for the full sensor. The producer owns the sampling coordinates. */\nexport type SensorRawProducerExposureWindowInput = Omit<CalculateCaptureExposureWindowsInput,\n \"nativeRaster\" | \"activeCaptureRect\" | \"samplePointsNative\">;\n/** Input for one bounded frame. It is never a conversion from separate RGB pixels. */\nexport interface SensorRawProducerInput {\n frame: Omit<SensorRawFrameInput, \"samples\">;\n sites: readonly SensorRawProducerSiteInput[];\n /** If omitted, every event uses the existing global window 0..shutterSeconds. */\n exposureWindow?: SensorRawProducerExposureWindowInput;\n}\n/** Codes produced by the engine, with per-step diagnostics. The upstream radiance and response are as declared, not verified. */\nexport interface SensorRawProducerResult {\n schemaVersion: typeof SENSOR_RAW_PRODUCER_SCHEMA_VERSION;\n codeProducer: \"engine-charge-capacity-noise-adc\";\n upstreamOrigin: \"declared-eqe-and-dark-exposure-results\";\n upstreamRadiometryVerified: false;\n seedSchedule: \"murmur3-capture-seed-native-index-stream-v2\";\n frame: SensorRawFrame;\n localExposureWindows?: CalculationResult<CaptureExposureWindows>;\n sites: readonly {\n accumulatedCharge: ReturnType<typeof composeSensorAccumulatedCharge>;\n capacity: ReturnType<typeof assessSensorPhysicalChargeCapacity>;\n realization: ReturnType<typeof simulateSensorChargeRealization>;\n readout: ReturnType<typeof simulateSensorRawCode>;\n }[];\n}\nfunction fields(value: unknown, allowed: readonly string[]): Record<string, unknown> {\n return requireAllowlistedRecord(value, allowed, \"Invalid sensor RAW producer fields.\");\n}\nfunction publicId(value: unknown): string {\n return requirePublicOpaqueId(value, \"Expected public producer identity.\");\n}\nconst KEY_RECURSE = 0, KEY_IDENTITY = 1, KEY_IDENTITY_LIST = 2;\n/** Bounded cache of how the identity check classifies each property name (it depends only on the name). */\nconst IDENTITY_KEY_KINDS = new Map<string, number>();\n/** Bounded cache of strings already known to be valid public IDs (validity depends only on the string). */\nconst VALID_PUBLIC_IDS = new Set<string>();\nconst IDENTITY_WALK_MEMO_LIMIT = 4096;\nfunction identityKeyKind(key: string): number {\n // Array indices and other names ending in a digit match neither suffix.\n const last = key.charCodeAt(key.length - 1);\n if (last >= 48 && last <= 57) return KEY_RECURSE;\n let kind = IDENTITY_KEY_KINDS.get(key);\n if (kind === undefined) {\n kind = /(?:Id|Version)$/.test(key) ? KEY_IDENTITY : /Ids$/.test(key) ? KEY_IDENTITY_LIST : KEY_RECURSE;\n if (IDENTITY_KEY_KINDS.size < IDENTITY_WALK_MEMO_LIMIT) IDENTITY_KEY_KINDS.set(key, kind);\n }\n return kind;\n}\nfunction memoizedPublicId(value: unknown): void {\n if (typeof value === \"string\" && VALID_PUBLIC_IDS.has(value)) return;\n publicId(value);\n if (VALID_PUBLIC_IDS.size < IDENTITY_WALK_MEMO_LIMIT) VALID_PUBLIC_IDS.add(value as string);\n}\n/**\n * At any depth, every property whose name ends in Id or Version must hold a public ID, and every property\n * ending in Ids a bounded dense list of them. Order, keys and errors are the same as the earlier\n * Object.entries walk. Key classification and already-valid IDs are cached, because each depends only on\n * its string.\n */\nfunction publicIdentities(value: unknown): void {\n if (value === null || typeof value !== \"object\") return;\n const record = value as Record<string, unknown>, keys = Object.keys(record);\n for (let index = 0; index < keys.length; index++) {\n const key = keys[index]!, kind = identityKeyKind(key), child = record[key];\n if (kind === KEY_IDENTITY) memoizedPublicId(child);\n else if (kind === KEY_IDENTITY_LIST) dense(child, 256).forEach(memoizedPublicId);\n else if (child !== null && typeof child === \"object\") publicIdentities(child);\n }\n}\nfunction dense(value: unknown, maximum: number): unknown[] {\n if (!Array.isArray(value) || value.length > maximum || Array.from({ length: value.length }, (_, i) => i in value).includes(false)) {\n throw new InvalidConfigurationError(\"Expected bounded dense producer array.\");\n }\n return value;\n}\nfunction optionalEvidence(value: unknown): ReturnType<typeof parseEvidenceList> {\n return dense(value, 256).length === 0 ? [] : parseEvidenceList(value, \"optionalExposureEvidence\");\n}\nfunction exposureEvidence(value: unknown, temporalPhoto?: Record<string, unknown>): ComposeSensorAccumulatedChargeInput[\"photoSignal\"][\"componentEvidence\"] {\n if (temporalPhoto !== undefined) return parseSensorEqeTemporalPhotoSignal({ ...temporalPhoto, componentEvidence: value }).componentEvidence;\n const r = fields(value, [\"stationarity\", \"exposureBinding\"]);\n const b = fields(r.exposureBinding, [\"binding\", \"colorSamplingProfile\", \"nominalExposureDuration\", \"openingBoundary\", \"closingBoundary\"]);\n return { stationarity: parseEvidenceList(r.stationarity, \"stationarity\"), exposureBinding: {\n binding: parseEvidenceList(b.binding, \"binding\"), colorSamplingProfile: parseEvidenceList(b.colorSamplingProfile, \"colorSamplingProfile\"),\n nominalExposureDuration: parseEvidenceList(b.nominalExposureDuration, \"nominalExposureDuration\"),\n openingBoundary: optionalEvidence(b.openingBoundary), closingBoundary: optionalEvidence(b.closingBoundary) } };\n}\nconst common = [\"colorSamplingProfileId\", \"channelId\", \"site\", \"bindingId\", \"stationarityProfileId\", \"timeReference\",\n \"startOffsetSecondsFromOpeningReference\", \"endOffsetSecondsFromOpeningReference\", \"localExposureDurationSeconds\", \"componentEvidence\"];\nconst photoTrue: string[] = [\"timeStationarityEstablished\", ...PHOTO_SIGNAL_TRUE_FIELDS];\nconst photoFalse: string[] = [\"timeVaryingSignalIntegrated\", ...PHOTO_SIGNAL_DOWNSTREAM_FALSE_FIELDS];\nfunction chargeInput(value: unknown): ComposeSensorAccumulatedChargeInput {\n const r = fields(value, [\"photoSignal\", \"darkCharge\", \"additionalChargeComponents\", \"completenessProfile\"]);\n const temporal = r.photoSignal !== null && typeof r.photoSignal === \"object\" &&\n (r.photoSignal as Record<string, unknown>).kind === \"eqe-temporal-photo-signal\";\n const p = temporal ? parseSensorEqeTemporalPhotoSignal(r.photoSignal) as unknown as Record<string, unknown> : fields(r.photoSignal, [...common, ...photoTrue, ...photoFalse, \"kind\", \"stationarityStatus\", \"integrationMethod\",\n \"accumulatedSignalCompleteness\", \"incidentPhotonRatePerSecond\", \"expectedGeneratedElectronRatePerSecond\", \"expectedIncidentPhotonCount\", \"expectedGeneratedElectronCount\"]);\n const darkFalse = [\"integerDarkElectronCountSampled\", \"darkShotNoiseApplied\", \"darkCurrentCompensationApplied\", \"photoSignalIncluded\",\n \"otherChargeIncluded\", \"physicalFullWellAssessmentAuthorized\", \"saturationAssessed\"];\n const d = fields(r.darkCharge, [...common, ...darkFalse, \"darkCurrentProfileId\", \"operatingTemperatureC\", \"temperatureModel\",\n \"temperatureInterpolationUsed\", \"temporalIntegrationId\", \"darkCurrentElectronsPerSecond\", \"expectedDarkElectronCount\", \"countMeaning\", \"expectationValueOnly\", \"spatialDarkCurrentNonuniformityModeled\"]);\n if ((!temporal && (p.kind !== \"eqe-expected-counts\" || p.integrationMethod !== \"constant-rate-times-local-exposure-duration\" ||\n p.accumulatedSignalCompleteness !== \"photo-signal-only\" || (p.stationarityStatus !== \"established\" && p.stationarityStatus !== \"approximation\") ||\n photoTrue.some((k) => p[k] !== true) || photoFalse.some((k) => p[k] !== false))) || darkFalse.some((k) => d[k] !== false) ||\n d.expectationValueOnly !== true || d.countMeaning !== \"expected-thermally-generated-electrons\" ||\n typeof d.spatialDarkCurrentNonuniformityModeled !== \"boolean\" || typeof d.temperatureInterpolationUsed !== \"boolean\" ||\n (d.temperatureModel !== \"fixed-reference-temperature\" && d.temperatureModel !== \"piecewise-linear-temperature-table\" &&\n d.temperatureModel !== \"log-linear-temperature-table\")) {\n throw new InvalidConfigurationError(\"Producer requires untreated EQE/dark exposure expectations, not sampled, clipped or A/W charge.\");\n }\n if (d.temperatureModel === \"fixed-reference-temperature\" && d.temperatureInterpolationUsed !== false) {\n throw new InvalidConfigurationError(\"Fixed-temperature dark result cannot claim temperature interpolation.\");\n }\n for (const record of [p, d]) {\n for (const k of [\"colorSamplingProfileId\", \"channelId\", \"bindingId\", temporal ? \"temporalIntegrationId\" : \"stationarityProfileId\"]) publicId(record[k]);\n fields(record.site, [\"x\", \"y\"]);\n if (record.timeReference !== \"first-opening-boundary-phase\") throw new InvalidConfigurationError(\"Unsupported producer time origin.\");\n }\n publicId(d.darkCurrentProfileId);\n for (const [record, keys] of [[p, [\"incidentPhotonRatePerSecond\", \"expectedGeneratedElectronRatePerSecond\", \"expectedIncidentPhotonCount\", \"expectedGeneratedElectronCount\"]],\n [d, [\"darkCurrentElectronsPerSecond\", \"expectedDarkElectronCount\"]]] as const) {\n for (const k of keys) if (!(temporal && record === p && k.endsWith(\"RatePerSecond\")) && (typeof record[k] !== \"number\" || !Number.isFinite(record[k]) || record[k] < 0)) throw new InvalidConfigurationError(\"Invalid expected rates/counts.\");\n }\n const duration = p.localExposureDurationSeconds;\n if (typeof duration !== \"number\" || !Number.isFinite(duration) || duration <= 0 ||\n (!temporal && (p.expectedIncidentPhotonCount !== (p.incidentPhotonRatePerSecond as number)*duration ||\n p.expectedGeneratedElectronCount !== (p.expectedGeneratedElectronRatePerSecond as number)*duration)) ||\n d.expectedDarkElectronCount !== (d.darkCurrentElectronsPerSecond as number)*duration ||\n (p.expectedGeneratedElectronCount as number) > (p.expectedIncidentPhotonCount as number)) {\n throw new InvalidConfigurationError(\"Exposure expectations must match their exact temporal integral or constant-rate products and EQE domain.\");\n }\n const e = fields(d.componentEvidence, [\"darkCurrent\", \"siteApproximation\", \"exposure\"]);\n const charge = { photoSignal: { ...p, componentEvidence: exposureEvidence(p.componentEvidence, temporal ? p : undefined) },\n darkCharge: { ...d, componentEvidence: { darkCurrent: parseEvidenceList(e.darkCurrent, \"darkCurrent\"),\n siteApproximation: optionalEvidence(e.siteApproximation), exposure: exposureEvidence(e.exposure, temporal ? p : undefined) } },\n completenessProfile: parseSensorAccumulatedChargeCompletenessProfile(r.completenessProfile),\n ...(r.additionalChargeComponents === undefined ? {} : { additionalChargeComponents:\n dense(r.additionalChargeComponents, 32).map(parseSensorAdditionalStoredChargeComponent) }) } as unknown as ComposeSensorAccumulatedChargeInput;\n // The existing charge composition checks that photo, dark, additional and completeness events agree exactly.\n composeSensorAccumulatedCharge(charge);\n return charge;\n}\nfunction localWindows(frame: SensorRawProducerInput[\"frame\"], value: unknown): CalculationResult<CaptureExposureWindows> {\n const r = fields(value, [\"shutterMechanism\", \"nominalExposureDurationSeconds\", \"opening\", \"closing\"]);\n fields(r.nominalExposureDurationSeconds, [\"value\", \"unit\", \"evidence\"]);\n for (const boundary of [r.opening, r.closing]) {\n const b = fields(boundary, [\"kind\", \"directionNative\", \"traversalDurationSeconds\"]);\n if (b.directionNative !== undefined) fields(b.directionNative, [\"value\", \"evidence\"]);\n if (b.traversalDurationSeconds !== undefined) fields(b.traversalDurationSeconds, [\"value\", \"unit\", \"evidence\"]);\n }\n const native = frame.capture.geometry.nativeRaster;\n const timing = calculateCaptureExposureWindows({\n ...r as unknown as SensorRawProducerExposureWindowInput,\n nativeRaster: native,\n samplePointsNative: Array.from({ length: native.pixelWidth*native.pixelHeight }, (_, i) => ({\n x: i%native.pixelWidth+0.5, y: Math.floor(i/native.pixelWidth)+0.5\n }))\n });\n if (timing.value.nominalExposureDurationSeconds.value !== frame.capture.exposure.shutterSeconds) {\n throw new InvalidConfigurationError(\"Exposure schedule nominal duration differs from committed capture.\");\n }\n return timing;\n}\nfunction sourceBoundary(schedule: CaptureExposureWindows[\"opening\"][\"schedule\"]): SensorRawProducerExposureWindowInput[\"opening\"] {\n return schedule.kind === \"simultaneous\" ? { kind: \"simultaneous\" } : {\n kind: \"uniform-linear-native-scan\", directionNative: schedule.directionNative,\n traversalDurationSeconds: schedule.traversalDurationSeconds\n };\n}\n/** Internal: per-site validation shared by the reference path and bounded packed execution. */\nexport type NativeRawProducerFrameContext = Omit<SensorRawProducerInput[\"frame\"], \"capture\"> & {\n capture: Pick<SensorRawProducerInput[\"frame\"][\"capture\"], \"geometry\" | \"exposure\" | \"noise\" | \"focus\" | \"sceneStateId\" | \"sceneTimeSeconds\">;\n};\nexport function parseNativeRawProducerSite(site: unknown, i: number, frame: NativeRawProducerFrameContext,\n window?: CaptureExposureWindows[\"samples\"][number]): SensorRawProducerSiteInput {\n const native = frame.capture.geometry.nativeRaster;\n const s = fields(site, [\"charge\", \"samplingProfile\", \"capacityProfile\", \"operatingStateId\", \"readoutProfile\", \"regimeId\", \"fixedPatternNoise\"]);\n const charge = chargeInput(s.charge), p = charge.photoSignal;\n const contributors = resolveCaptureModeColorSamplingContributors({ nativeRaster: native, captureModeProfile: frame.captureModeProfile,\n modeId: frame.modeId, colorSamplingProfile: frame.colorSamplingProfile, bindingProfile: frame.bindingProfile,\n modeSampleIndexFullFrame: { x: i%native.pixelWidth, y: Math.floor(i/native.pixelWidth) } });\n\n if (contributors.totalContributorSites !== 1 || contributors.channelComposition.kind !== \"single-channel\" ||\n p.colorSamplingProfileId !== frame.colorSamplingProfile.profileId || p.channelId !== contributors.channelComposition.channelId ||\n p.site.x !== contributors.colorSamplingSiteRect.x || p.site.y !== contributors.colorSamplingSiteRect.y ||\n p.bindingId !== frame.bindingProfile.bindingId || p.startOffsetSecondsFromOpeningReference !== (window?.startOffsetSecondsFromOpeningReference ?? 0) ||\n p.endOffsetSecondsFromOpeningReference !== (window?.endOffsetSecondsFromOpeningReference ?? frame.capture.exposure.shutterSeconds) ||\n p.localExposureDurationSeconds !== (window?.localExposureDurationSeconds ?? frame.capture.exposure.shutterSeconds)) {\n throw new InvalidConfigurationError(\"Charge site/channel/binding/local exposure differs from committed capture.\");\n }\n const readoutProfile = parseSensorReadoutConversionProfile(s.readoutProfile);\n const isoGain = readoutProfile.regimes.find((regime) => regime.regimeId === s.regimeId)?.exposureIndexGain;\n if (isoGain !== undefined && isoGain.exposureIndex !== frame.capture.exposure.iso) {\n throw new InvalidConfigurationError(\"Readout regime ISO gain differs from the committed capture ISO.\");\n }\n return { charge, samplingProfile: parseSensorChargeSamplingProfile(s.samplingProfile), capacityProfile: parseSensorPhysicalChargeCapacityProfile(s.capacityProfile),\n operatingStateId: publicId(s.operatingStateId), readoutProfile, regimeId: publicId(s.regimeId),\n ...(s.fixedPatternNoise === undefined ? {} : { fixedPatternNoise: parseSensorFixedPatternNoiseProfile(s.fixedPatternNoise) }) };\n}\nexport function validateNativeRawReadoutIdentity(s: SensorRawProducerSiteInput, first: SensorRawProducerSiteInput): void {\n publicIdentities(s);\n const readout = resolveSensorReadoutRegime({ profile: s.readoutProfile, regimeId: s.regimeId });\n if (s.readoutProfile.profileId !== first.readoutProfile.profileId || s.regimeId !== first.regimeId ||\n readout.regime.adc.bitDepth > 16 || readout.regime.adc.digitalSaturationCode <= readout.regime.adc.blackLevelCode ||\n s.readoutProfile.colorSamplingProfileId !== s.charge.photoSignal.colorSamplingProfileId ||\n s.readoutProfile.channelId !== s.charge.photoSignal.channelId || s.samplingProfile.completenessProfileId !== s.charge.completenessProfile.profileId ||\n s.fixedPatternNoise?.profileId !== first.fixedPatternNoise?.profileId ||\n s.fixedPatternNoise?.sensorInstanceSeedUint32 !== first.fixedPatternNoise?.sensorInstanceSeedUint32) {\n throw new InvalidConfigurationError(\"Frame requires one readout identity/regime, one fixed-pattern identity and a positive uint16 RAW code span.\");\n }\n}\n/** The shared per-site pipeline holds all the charge, capacity, random-noise and ADC equations. `i` is the absolute native row-major index. */\nexport function calculateNativeRawSite(s: SensorRawProducerSiteInput, seed: number, i: number,\n /** Internal (#534): a build-up fraction's stage, which splits the realized counts down to the fraction and reads with its own stream. */\n b?: ExposureBuildUpStage): SensorRawProducerResult[\"sites\"][number] {\n const accumulatedCharge = composeSensorAccumulatedCharge(s.charge);\n const capacity = assessSensorPhysicalChargeCapacity({ accumulatedCharge: accumulatedCharge.value, capacityProfile: s.capacityProfile,\n operatingStateId: s.operatingStateId, operatingTemperatureC: s.charge.darkCharge.operatingTemperatureC });\n const pattern = s.fixedPatternNoise === undefined ? {} : { fixedPatternNoise: s.fixedPatternNoise };\n let realization = simulateSensorChargeRealization({ accumulatedCharge: accumulatedCharge.value, samplingProfile: s.samplingProfile,\n seedUint32: deriveNativeSiteStreamSeedUint32(seed, i, NATIVE_SITE_CHARGE_STREAM_ID), ...pattern });\n if (b) {\n const v = realization.value;\n if (v.additionalComponents.length) throw new InvalidConfigurationError(\"An exposure build-up takes photo and dark charge only.\");\n b.split(i, v.photoSampledMeanElectronCount, v.darkSampledMeanElectronCount, v.photoRealizedElectronCount, v.darkRealizedElectronCount);\n realization = { ...realization, value: { ...v, photoRealizedElectronCount: b.photo, darkRealizedElectronCount: b.dark, totalRealizedStoredElectronEquivalentCount: b.photo + b.dark + 0 } };\n }\n const readout = simulateSensorRawCode({ chargeRealization: realization.value, physicalCapacityAssessment: capacity.value,\n readoutProfile: s.readoutProfile, regimeId: s.regimeId,\n readNoiseSeedUint32: deriveNativeSiteStreamSeedUint32(seed, i, b ? b.read : NATIVE_SITE_READ_NOISE_STREAM_ID), ...pattern });\n return { accumulatedCharge, capacity, realization, readout };\n}\n/** The selected regime's declared INL, which the effective white level needs at saturation. */\nfunction regimeInl(site: SensorRawProducerSiteInput): { adcIntegralNonLinearity?: NonNullable<SensorReadoutConversionProfile[\"regimes\"][number][\"adc\"][\"integralNonLinearity\"]> } {\n const inl = site.readoutProfile.regimes.find((r) => r.regimeId === site.regimeId)?.adc.integralNonLinearity;\n return inl === undefined ? {} : { adcIntegralNonLinearity: inl };\n}\n/** Validates the complete per-site exposure inputs. Charge, noise or RAW codes are never accepted as a shortcut. */\nexport function parseSensorRawProducerInput(value: unknown): SensorRawProducerInput {\n const r = fields(value, [\"frame\", \"sites\", \"exposureWindow\"]), f = fields(r.frame, [\"frameId\", \"capture\", \"modeId\", \"captureModeProfile\", \"colorSamplingProfile\", \"bindingProfile\", \"containerBitDepth\"]);\n const capture = parseSimulatedCapture(f.capture), native = capture.geometry.nativeRaster, count = native.pixelWidth*native.pixelHeight;\n const sites = dense(r.sites, RAW_REFERENCE_MAX_NATIVE_SITES);\n const frame = { frameId: publicId(f.frameId), capture, modeId: publicId(f.modeId), containerBitDepth: 16 as const,\n captureModeProfile: parseCaptureModeProfile(f.captureModeProfile), colorSamplingProfile: parseSensorColorSamplingProfile(f.colorSamplingProfile),\n bindingProfile: parseNativeEffectiveRasterColorSamplingBindingProfile(f.bindingProfile) };\n const mode = frame.captureModeProfile.modes.find((m) => m.modeId === frame.modeId);\n if (f.containerBitDepth !== 16 || count > RAW_REFERENCE_MAX_NATIVE_SITES || sites.length !== count ||\n capture.noise.model.id !== SENSOR_RAW_PRODUCER_NOISE_MODEL.id || capture.noise.model.version !== SENSOR_RAW_PRODUCER_NOISE_MODEL.version ||\n frame.colorSamplingProfile.layout.kind !== \"periodic-mosaic\" || !mode || mode.acquisition.kind !== \"single-frame\" ||\n mode.perFrameSampling.kind !== \"native-effective-raster\" || (mode.reconstructionStages?.length ?? 0) !== 0) {\n throw new InvalidConfigurationError(\"Producer requires exact noise identity and bounded single-frame native CFA coverage.\");\n }\n const timing = r.exposureWindow === undefined ? undefined : localWindows(frame, r.exposureWindow);\n const parsed = sites.map((site, i) => parseNativeRawProducerSite(site, i, frame, timing?.value.samples[i]));\n for (const site of parsed) validateNativeRawReadoutIdentity(site, parsed[0]!);\n publicIdentities(frame);\n return { frame, sites: parsed, ...(timing === undefined ? {} : { exposureWindow: {\n shutterMechanism: timing.value.shutterMechanism,\n nominalExposureDurationSeconds: timing.value.nominalExposureDurationSeconds,\n opening: sourceBoundary(timing.value.opening.schedule), closing: sourceBoundary(timing.value.closing.schedule)\n } }) };\n}\n/** Runs accumulated charge → capacity → Poisson noise → read noise and ADC → native sample → immutable frame. */\nexport function simulateSensorRawFrame(input: SensorRawProducerInput): CalculationResult<SensorRawProducerResult> {\n const v = parseSensorRawProducerInput(input), seed = v.frame.capture.noise.seedUint32;\n const sites = v.sites.map((s, i) => calculateNativeRawSite(s, seed, i));\n const native = v.frame.capture.geometry.nativeRaster;\n const samples = sites.map((s, i) => createSensorRawCaptureSample({ rawCode: s.readout.value,\n ...regimeInl(v.sites[i]!),\n contributors: resolveCaptureModeColorSamplingContributors({ nativeRaster: native, captureModeProfile: v.frame.captureModeProfile,\n modeId: v.frame.modeId, colorSamplingProfile: v.frame.colorSamplingProfile, bindingProfile: v.frame.bindingProfile,\n modeSampleIndexFullFrame: { x: i%native.pixelWidth, y: Math.floor(i/native.pixelWidth) } }) }));\n return approximationResult({ schemaVersion: SENSOR_RAW_PRODUCER_SCHEMA_VERSION, codeProducer: \"engine-charge-capacity-noise-adc\",\n upstreamOrigin: \"declared-eqe-and-dark-exposure-results\", upstreamRadiometryVerified: false,\n seedSchedule: \"murmur3-capture-seed-native-index-stream-v2\", frame: createSensorRawFrame({ ...v.frame, samples }), sites,\n ...(v.exposureWindow === undefined ? {} : { localExposureWindows: localWindows(v.frame, v.exposureWindow) }) },\n \"native-sensor-raw-frame-producer\", SENSOR_RAW_PRODUCER_SCHEMA_VERSION, [\n \"Untreated EQE/dark exposure results and completeness evidence are upstream declarations; source radiometry is not independently verified\",\n \"Native row-major site seeds are MurmurHash3_x86_32 of (capture seed, absolute native index, stream 0 charge / 1 read noise); deterministic and non-cryptographic\",\n \"Existing scalar capacity/noise/readout approximations retain distinct physical/pre-ADC/digital saturation diagnostics; no blooming\",\n \"Optional fixed-pattern noise is deterministic per sensor instance (its own seed and absolute colour-sampling site), independent of the capture seed\",\n \"Stationarity applies separately to every exact local window; no time-varying radiance integration, multi-frame acquisition, RGB-to-RAW conversion or production-stage activation\",\n \"Stored capture float planes remain independent; same-RAW export must use the returned frame's reconstruction handoff\"]);\n}\n"]}
@@ -31,3 +31,5 @@ export declare function fullRect(raster: {
31
31
  width: number;
32
32
  height: number;
33
33
  };
34
+ /** |actual − expected| ≤ tolerance · max(1, |actual|, |expected|): the parsers' shared consistency check (default 1e-10). */
35
+ export declare function approximatelyEqual(actual: number, expected: number, tolerance?: number): boolean;
@@ -31,4 +31,8 @@ export function sameSite(a, b) {
31
31
  export function fullRect(raster) {
32
32
  return { x: 0, y: 0, width: raster.pixelWidth, height: raster.pixelHeight };
33
33
  }
34
+ /** |actual − expected| ≤ tolerance · max(1, |actual|, |expected|): the parsers' shared consistency check (default 1e-10). */
35
+ export function approximatelyEqual(actual, expected, tolerance = 1e-10) {
36
+ return Math.abs(actual - expected) <= tolerance * Math.max(1, Math.abs(actual), Math.abs(expected));
37
+ }
34
38
  //# sourceMappingURL=shared-helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared-helpers.js","sourceRoot":"","sources":["../../src/core/shared-helpers.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;GAGG;AAEH,2GAA2G;AAC3G,MAAM,UAAU,UAAU,CAAI,KAAQ;IACpC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACrB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,KAAgC,CAAC;QAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IACvF,OAAO,KAAK,CAAC;AACf,CAAC;AACD,gCAAgC;AAChC,MAAM,UAAU,SAAS,CAAI,KAAQ;IACnC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAM,CAAC;AAChD,CAAC;AAGD,4DAA4D;AAC5D,MAAM,UAAU,cAAc,CAAC,KAAqB,EAAE,KAAa;IACjE,MAAM,QAAQ,GAAG,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC;IAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,GAAG,QAAQ,CAAC;IAClC,KAAK,CAAC,UAAU,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;IACjD,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC;AACnB,CAAC;AACD,2DAA2D;AAC3D,MAAM,UAAU,QAAQ,CAAC,CAA2B,EAAE,CAA2B;IAC/E,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC;AACD,qDAAqD;AACrD,MAAM,UAAU,QAAQ,CAAC,MAAmD;IAC1E,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;AAC9E,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Small helpers shared by several modules (2.19.0: these were private copies in each; one shared copy keeps the bundles\n * smaller). Behaviour is unchanged.\n */\n\n/** Freezes a value and every object it holds, depth first; already frozen objects are left as they are. */\nexport function deepFreeze<T>(value: T): T {\n if (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return value;\n Object.freeze(value);\n for (const child of Object.values(value as Record<string, unknown>)) deepFreeze(child);\n return value;\n}\n/** A deep copy of JSON data. */\nexport function cloneJson<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n}\n/** A running sum with Kahan compensation. */\nexport interface CompensatedSum { sum: number; correction: number }\n/** Adds `value` to a Kahan-compensated sum (Kahan 1965). */\nexport function addCompensated(state: CompensatedSum, value: number): void {\n const adjusted = value - state.correction;\n const next = state.sum + adjusted;\n state.correction = (next - state.sum) - adjusted;\n state.sum = next;\n}\n/** Whether two points (or sites) have the same x and y. */\nexport function sameSite(a: { x: number; y: number }, b: { x: number; y: number }): boolean {\n return a.x === b.x && a.y === b.y;\n}\n/** The whole raster as a rectangle at the origin. */\nexport function fullRect(raster: { pixelWidth: number; pixelHeight: number }): { x: number; y: number; width: number; height: number } {\n return { x: 0, y: 0, width: raster.pixelWidth, height: raster.pixelHeight };\n}\n"]}
1
+ {"version":3,"file":"shared-helpers.js","sourceRoot":"","sources":["../../src/core/shared-helpers.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;GAGG;AAEH,2GAA2G;AAC3G,MAAM,UAAU,UAAU,CAAI,KAAQ;IACpC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACrB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,KAAgC,CAAC;QAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IACvF,OAAO,KAAK,CAAC;AACf,CAAC;AACD,gCAAgC;AAChC,MAAM,UAAU,SAAS,CAAI,KAAQ;IACnC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAM,CAAC;AAChD,CAAC;AAGD,4DAA4D;AAC5D,MAAM,UAAU,cAAc,CAAC,KAAqB,EAAE,KAAa;IACjE,MAAM,QAAQ,GAAG,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC;IAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,GAAG,QAAQ,CAAC;IAClC,KAAK,CAAC,UAAU,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;IACjD,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC;AACnB,CAAC;AACD,2DAA2D;AAC3D,MAAM,UAAU,QAAQ,CAAC,CAA2B,EAAE,CAA2B;IAC/E,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC;AACD,qDAAqD;AACrD,MAAM,UAAU,QAAQ,CAAC,MAAmD;IAC1E,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;AAC9E,CAAC;AAED,6HAA6H;AAC7H,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,QAAgB,EAAE,SAAS,GAAG,KAAK;IACpF,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC,IAAI,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;AACtG,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Small helpers shared by several modules (2.19.0: these were private copies in each; one shared copy keeps the bundles\n * smaller). Behaviour is unchanged.\n */\n\n/** Freezes a value and every object it holds, depth first; already frozen objects are left as they are. */\nexport function deepFreeze<T>(value: T): T {\n if (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return value;\n Object.freeze(value);\n for (const child of Object.values(value as Record<string, unknown>)) deepFreeze(child);\n return value;\n}\n/** A deep copy of JSON data. */\nexport function cloneJson<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n}\n/** A running sum with Kahan compensation. */\nexport interface CompensatedSum { sum: number; correction: number }\n/** Adds `value` to a Kahan-compensated sum (Kahan 1965). */\nexport function addCompensated(state: CompensatedSum, value: number): void {\n const adjusted = value - state.correction;\n const next = state.sum + adjusted;\n state.correction = (next - state.sum) - adjusted;\n state.sum = next;\n}\n/** Whether two points (or sites) have the same x and y. */\nexport function sameSite(a: { x: number; y: number }, b: { x: number; y: number }): boolean {\n return a.x === b.x && a.y === b.y;\n}\n/** The whole raster as a rectangle at the origin. */\nexport function fullRect(raster: { pixelWidth: number; pixelHeight: number }): { x: number; y: number; width: number; height: number } {\n return { x: 0, y: 0, width: raster.pixelWidth, height: raster.pixelHeight };\n}\n\n/** |actual − expected| ≤ tolerance · max(1, |actual|, |expected|): the parsers' shared consistency check (default 1e-10). */\nexport function approximatelyEqual(actual: number, expected: number, tolerance = 1e-10): boolean {\n return Math.abs(actual - expected) <= tolerance * Math.max(1, Math.abs(actual), Math.abs(expected));\n}\n"]}
@@ -6,4 +6,4 @@
6
6
  * own versions. Release checks confirm it matches package.json and the packed package.
7
7
  * @see docs/RELEASE_1_0_1.md
8
8
  */
9
- export declare const ENGINE_API_VERSION: "2.19.0";
9
+ export declare const ENGINE_API_VERSION: "2.21.0";
@@ -7,5 +7,5 @@
7
7
  * own versions. Release checks confirm it matches package.json and the packed package.
8
8
  * @see docs/RELEASE_1_0_1.md
9
9
  */
10
- export const ENGINE_API_VERSION = "2.19.0";
10
+ export const ENGINE_API_VERSION = "2.21.0";
11
11
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/core/version.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,QAAiB,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Version of the engine release. Since 1.0.1 it equals the npm package version.\n *\n * New captures and plans record this version as their creator. Archived records keep the\n * version they were made with. Proof-of-concept (POC), schema and model contracts have their\n * own versions. Release checks confirm it matches package.json and the packed package.\n * @see docs/RELEASE_1_0_1.md\n */\nexport const ENGINE_API_VERSION = \"2.19.0\" as const;\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/core/version.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,QAAiB,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Version of the engine release. Since 1.0.1 it equals the npm package version.\n *\n * New captures and plans record this version as their creator. Archived records keep the\n * version they were made with. Proof-of-concept (POC), schema and model contracts have their\n * own versions. Release checks confirm it matches package.json and the packed package.\n * @see docs/RELEASE_1_0_1.md\n */\nexport const ENGINE_API_VERSION = \"2.21.0\" as const;\n"]}
@@ -2,7 +2,9 @@ import type { EvidenceProvenance } from "../core/evidence-provenance.js";
2
2
  import type { LensProjectionModel } from "../camera/lens-projection.js";
3
3
  import type { RadialDistortionProfile } from "../optics/radial-distortion.js";
4
4
  import type { IlluminationVignettingProfile } from "../optics/illumination-vignetting.js";
5
- export type GenericLensSet = "professional" | "consumer";
5
+ import type { DefocusBokehOptions } from "../optics/defocus-bokeh-kernel.js";
6
+ /** #554: "phone", the three fixed lenses of a phone sensor profile (`sensor.profile` with `fixedLenses: "phone"`). */
7
+ export type GenericLensSet = "professional" | "consumer" | "phone";
6
8
  export type GenericLensKind = "standard" | "macro" | "fisheye";
7
9
  /** The character of a set, at each lens's widest aperture. Aberrations are in waves at 550 nm at the frame corner. */
8
10
  export interface GenericLensCharacterValues {
@@ -22,7 +24,7 @@ export interface GenericLensCharacterValues {
22
24
  distortionMagnitude: number;
23
25
  /** Corner fall-off in stops that stays when stopped down (natural vignetting). */
24
26
  naturalVignettingStops: number;
25
- /** Extra corner fall-off in stops at the widest aperture (optical vignetting); gone two stops down. */
27
+ /** Extra corner fall-off in stops at the widest aperture (optical vignetting); gone four stops down (N = 4·N0). */
26
28
  opticalVignettingStops: number;
27
29
  /** Veiling glare: the fraction of the image's mean irradiance spread as a uniform veil. */
28
30
  veilingGlareFraction: number;
@@ -60,13 +62,13 @@ export interface GenericLensCatalogueEntry {
60
62
  note: string;
61
63
  /**
62
64
  * A short plain-English summary of the lens's character (at most 40 characters, US spelling), written from its adjustments and
63
- * `note`, for lists and pickers. It describes only what the catalogue models (bokeh shape is not modeled: the defocus is a disc).
65
+ * `note`, for lists and pickers. It describes the lens's sharpness, color, distortion and falloff, not its bokeh (the same rule for every lens of a set).
64
66
  */
65
67
  summary: string;
66
68
  }
67
69
  /** The set baselines (owner's table, #549), each lens's starting point before its adjustments. */
68
70
  export declare const GENERIC_LENS_SET_BASELINES: Readonly<Record<GenericLensSet, Readonly<GenericLensCharacterValues>>>;
69
- /** The 30 lenses: 17 professional, then 13 consumer, each set by focal length. */
71
+ /** The 33 lenses: 17 professional, 13 consumer and (#554) 3 phone lenses, each set by focal length. */
70
72
  export declare const GENERIC_LENS_CATALOGUE: readonly GenericLensCatalogueEntry[];
71
73
  /** The catalogue ids, in catalogue order. */
72
74
  export declare const GENERIC_LENS_IDS: readonly string[];
@@ -119,6 +121,11 @@ export interface GenericLensCharacter {
119
121
  };
120
122
  /** Standard deviation of the autofocus error as a fraction of the depth of focus 2·N·c. */
121
123
  focusScatterDepthOfFocusFraction: number;
124
+ /**
125
+ * Bokeh character (#567) at this f-number, focus and sensor, as the options of `lens.defocus` and `calculateDefocusBokehKernel`
126
+ * (#553): blades, the resolved W040 as `sphericalAberration` (µm at this f-number) and, for fast wides and normals, `catsEye`.
127
+ */
128
+ bokeh: DefocusBokehOptions;
122
129
  }
123
130
  export interface ResolvedGenericLens {
124
131
  lensId: string;
@@ -24,7 +24,14 @@
24
24
  * D(λ) = (1/λ² − 1/λ_d²)/(1/λ_F² − 1/λ_C²) (Fraunhofer d, F and C lines; `calculateCauchyRefractiveIndex`).
25
25
  * - Distortion: radial r_d = r·(1 + k1·ρ²), ρ normalised to the frame's half-diagonal, so k1 is the corner distortion.
26
26
  * - Vignetting: relative illumination E(ρ) = (1 − b·ρ²)² with E(1) = 2^−s, s the corner fall-off in stops: a natural part,
27
- * plus an optical part that fades over the first two stops of stopping down.
27
+ * plus an optical part that fades over the first four stops of stopping down (log2(N/N0) = 2 is four stops, since a
28
+ * stop is a factor √2 in N).
29
+ * - Bokeh (#567), the options of `lens.defocus` (#553) that `simulateCapture` folds into the PSF with `lens.defocus`: rounded
30
+ * aperture blades (9 at curvature 0.7 for the professional set, 7 at 0.3 for the consumer set, open to a circle at the widest
31
+ * aperture), the lens's own W040 as `sphericalAberration`, and, for the fast (f/2 or faster) rectilinear wides and normals
32
+ * (at most 50 mm equivalent), a cat's eye: one clipping circle of the widest pupil's radius whose shift leaves the open area
33
+ * 2^−s_o of the pupil at the frame corner wide open, s_o the lens's optical vignetting in stops (the light it removes is the
34
+ * optical part of the relative illumination above; the kernel is a shape only).
28
35
  * - Flare, focus breathing and focus consistency are numbers for callers; `simulateCapture` renders none of them.
29
36
  * @see docs/LENS_CATALOGUE.md for the tables, the adjustments and why each lens has them.
30
37
  */
@@ -33,6 +40,7 @@ import { InvalidScientificInputError } from "../core/validation.js";
33
40
  import { requireInputKeys, requireInputObject } from "../core/record-validation.js";
34
41
  import { calculateEquivalentFocalLength35Mm } from "../camera/equivalent-focal-length.js";
35
42
  import { FRAUNHOFER_C_LINE_NM, FRAUNHOFER_D_LINE_NM, FRAUNHOFER_F_LINE_NM } from "../optics/longitudinal-chromatic-aberration.js";
43
+ import { portableAsin } from "../core/portable-math.js";
36
44
  import { GENERIC_PRIME_MINIMUM_FOCUS, GENERIC_PRIME_THIRD_STOP_F_NUMBERS } from "./generic-prime-lenses.js";
37
45
  import { createDeterministicUniformStream, deriveNativeSiteStreamSeedUint32, sampleDeterministicStandardNormal } from "../sensor/stochastic-seed.js";
38
46
  /** The set baselines (owner's table, #549), each lens's starting point before its adjustments. */
@@ -42,7 +50,12 @@ export const GENERIC_LENS_SET_BASELINES = /* @__PURE__ */ Object.freeze({
42
50
  breathingFraction: -0.03, focusScatterDepthOfFocusFraction: 0.1, closeFocusFactor: 0.15 }),
43
51
  consumer: /* @__PURE__ */ Object.freeze({ sphericalWaves: 0.5, comaWaves: 1.0, astigmatismWaves: 0.8, fieldCurvatureWaves: 0.45, axialColorWaves: 0.4,
44
52
  lateralColorFraction: 0.0003, distortionMagnitude: 0.03, naturalVignettingStops: 0.7, opticalVignettingStops: 1.1, veilingGlareFraction: 0.02, ghostFraction: 0.008,
45
- breathingFraction: -0.08, focusScatterDepthOfFocusFraction: 0.3, closeFocusFactor: 0.5 })
53
+ breathingFraction: -0.08, focusScatterDepthOfFocusFraction: 0.3, closeFocusFactor: 0.5 }),
54
+ // #554: design values (docs/LENS_CATALOGUE.md, "Phone lenses"): the consumer baseline with the stronger fall-off, flare and distortion
55
+ // (corrected in software on phones) of small fixed-aperture phone lenses, and no optical-vignetting change (the aperture is fixed).
56
+ phone: /* @__PURE__ */ Object.freeze({ sphericalWaves: 0.5, comaWaves: 1.0, astigmatismWaves: 0.8, fieldCurvatureWaves: 0.5, axialColorWaves: 0.3,
57
+ lateralColorFraction: 0.0004, distortionMagnitude: 0.03, naturalVignettingStops: 1.2, opticalVignettingStops: 0.5, veilingGlareFraction: 0.03, ghostFraction: 0.01,
58
+ breathingFraction: -0.05, focusScatterDepthOfFocusFraction: 0.3, closeFocusFactor: 0.5 })
46
59
  });
47
60
  /** The generic smallest aperture of both sets: f/16 up to 16 mm, f/22 up to 135 mm, f/32 beyond (as `lens.prime`). */
48
61
  function narrowest(equivalent) { return equivalent <= 16 ? 16 : equivalent <= 135 ? 22 : 32; }
@@ -71,6 +84,14 @@ const PRO = [
71
84
  [800, 5.6, "standard", { distortion: 0.3, axialColor: 1.2, coma: 0.5, astigmatism: 0.5, vignetting: 0.7 }, "Super telephoto.", "Slow super telephoto; low coma"],
72
85
  [1200, 8, "standard", { distortion: 0.2, axialColor: 1.1, coma: 0.5, astigmatism: 0.5, vignetting: 0.6 }, "Slow extreme telephoto: little vignetting.", "Slow extreme telephoto; little falloff"]
73
86
  ];
87
+ // #554: the owner's phone lenses (13, 24 and 77 mm equivalents at f/2.2, f/1.8 and f/2.8, fixed apertures); adjustments are design values.
88
+ const PHONE = [
89
+ [13, 2.2, "standard", { distortion: -1.5, astigmatism: 1.3, fieldCurvature: 1.3, lateralColor: 1.5, vignetting: 1.2, strayLight: 1.2 },
90
+ "Phone ultra-wide: strong barrel distortion, softer corners and lateral colour, left to the phone's software correction.", "Strong barrel distortion; soft corners"],
91
+ [24, 1.8, "standard", { distortion: -0.5 }, "Phone main camera: the phone baseline.", "The phone baseline; mild barrel"],
92
+ [77, 2.8, "standard", { distortion: 0.4, coma: 0.7, astigmatism: 0.8, axialColor: 1.2, vignetting: 0.8 },
93
+ "Phone telephoto: a small field angle, so less coma and astigmatism; axial colour; slight pincushion.", "Telephoto; axial color, pincushion"]
94
+ ];
74
95
  const CONSUMER = [
75
96
  [16, 2.8, "standard", { distortion: -1.5, coma: 1.1, astigmatism: 1.2, fieldCurvature: 1.2, lateralColor: 1.3, vignetting: 1.2, strayLight: 1.2 },
76
97
  "Ultra-wide: strong barrel distortion and soft corners, left to the correction profile.", "Strong barrel distortion; soft corners"],
@@ -91,15 +112,15 @@ const CONSUMER = [
91
112
  ];
92
113
  function entry(set, [focal, widest, kind, adjustments, note, summary, fisheye]) {
93
114
  const special = kind === "macro" ? " Macro" : kind === "fisheye" ? " Fisheye" : "";
94
- const suffix = set === "professional" ? " Pro" : "";
115
+ const suffix = set === "professional" ? " Pro" : set === "phone" ? " Phone" : "";
95
116
  return Object.freeze({ lensId: ("pv-" + focal + "-" + widest + special + suffix).toLowerCase().replace(/ /g, "-"), name: "PV " + focal + " " + widest + special + suffix,
96
- set, kind, equivalentFocalLengthMm: focal, widestFNumber: widest, narrowestFNumber: narrowest(focal),
117
+ set, kind, equivalentFocalLengthMm: focal, widestFNumber: widest, narrowestFNumber: set === "phone" ? widest : narrowest(focal),
97
118
  maximumMagnification: kind === "macro" ? 1 : GENERIC_PRIME_MINIMUM_FOCUS.magnification, projection: kind === "fisheye" ? "fisheye-equisolid-angle" : "rectilinear",
98
119
  ...(fisheye ? { fisheyeImage: fisheye } : {}), adjustments: Object.freeze({ ...adjustments }), note, summary });
99
120
  }
100
- /** The 30 lenses: 17 professional, then 13 consumer, each set by focal length. */
121
+ /** The 33 lenses: 17 professional, 13 consumer and (#554) 3 phone lenses, each set by focal length. */
101
122
  export const GENERIC_LENS_CATALOGUE = /* @__PURE__ */ Object.freeze([...PRO.map((row) => entry("professional", row)),
102
- ...CONSUMER.map((row) => entry("consumer", row))]);
123
+ ...CONSUMER.map((row) => entry("consumer", row)), ...PHONE.map((row) => entry("phone", row))]);
103
124
  /** The catalogue ids, in catalogue order. */
104
125
  export const GENERIC_LENS_IDS = /* @__PURE__ */ Object.freeze(GENERIC_LENS_CATALOGUE.map((lens) => lens.lensId));
105
126
  /** Where the catalogue's numbers come from: Photivra's own choices, guided by openly published descriptions of lens behaviour. */
@@ -156,6 +177,21 @@ function resolvedDistortionReach(k1) {
156
177
  const r = GENERIC_LENS_RESOLVED_PROFILE_REACH;
157
178
  return k1 < 0 ? r / (1 + k1 * r * r) * 1.01 : r;
158
179
  }
180
+ /**
181
+ * The centre shift d (pupil radii) of a clipping circle of the pupil's radius that leaves the open fraction `open` of the pupil:
182
+ * the lens of two unit circles, (2/π)(acos(d/2) − (d/2)·√(1 − d²/4)) = open, by bisection (acos u = π/2 − asin u, portable).
183
+ */
184
+ function catsEyeShift(open) {
185
+ let low = 0, high = 2;
186
+ for (let k = 0; k < 52; k++) {
187
+ const d = (low + high) / 2, u = d / 2;
188
+ if ((Math.PI / 2 - portableAsin(u) - u * Math.sqrt(1 - u * u)) * 2 / Math.PI > open)
189
+ low = d;
190
+ else
191
+ high = d;
192
+ }
193
+ return (low + high) / 2;
194
+ }
159
195
  function positiveFinite(value, name) {
160
196
  if (typeof value !== "number" || !Number.isFinite(value) || value <= 0)
161
197
  throw new InvalidScientificInputError(name + " must be a positive finite number.");
@@ -185,6 +221,12 @@ export function resolveGenericLens(input) {
185
221
  const magnification = focusDistanceM === null ? 0 : f / (focusDistanceM - f), closeness = Math.min(1, magnification / maximumMagnification);
186
222
  const closeFocusGain = 1 + values.closeFocusFactor * closeness, a = lens.widestFNumber / fNumber;
187
223
  const cornerStops = values.naturalVignettingStops + values.opticalVignettingStops * Math.min(1, Math.max(0, 1 - Math.log2(fNumber / lens.widestFNumber) / 2));
224
+ // #567: the cat's eye of the fast (≤ f/2) rectilinear wides and normals (≤ 50 mm), resolved on this sensor (see the module comment).
225
+ const pro = lens.set === "professional", pupilMm = focalLengthMm / lens.widestFNumber / 2;
226
+ const bokeh = { blades: { count: pro ? 9 : 7, firstBladeEdgeAngleDegrees: 0, curvature: pro ? 0.7 : 0.3, circularAtOrBelowFNumber: lens.widestFNumber },
227
+ sphericalAberration: { w040Micrometers: values.sphericalWaves * a ** 4 * closeFocusGain * 0.55, atFNumber: fNumber },
228
+ ...(lens.kind === "standard" && lens.equivalentFocalLengthMm <= 50 && lens.widestFNumber <= 2 ? { catsEye: { apertures: [{ radiusMm: pupilMm,
229
+ shiftPerTanFieldMm: catsEyeShift(2 ** -values.opticalVignettingStops) * pupilMm * focalLengthMm / halfDiagonalMm }] } } : {}) };
188
230
  const character = { fNumber, focusDistanceM, magnification, closeFocusGain, pupilScale: a,
189
231
  aberrations: { sphericalWaves: values.sphericalWaves * a ** 4 * closeFocusGain, balancingDefocusWaves: -values.sphericalWaves * a ** 4 * closeFocusGain,
190
232
  comaWaves: values.comaWaves * a ** 3 * closeFocusGain, astigmatismWaves: values.astigmatismWaves * a * a * closeFocusGain,
@@ -194,7 +236,7 @@ export function resolveGenericLens(input) {
194
236
  vignetting: { profile: genericLensVignettingProfile(cornerStops, halfDiagonalMm, GENERIC_LENS_RESOLVED_PROFILE_REACH), cornerStops },
195
237
  strayLight: { veilingGlareFraction: values.veilingGlareFraction, ghostFraction: values.ghostFraction },
196
238
  breathing: { fieldOfViewChange: values.breathingFraction * closeness, atMinimumFocus: values.breathingFraction },
197
- focusScatterDepthOfFocusFraction: values.focusScatterDepthOfFocusFraction };
239
+ focusScatterDepthOfFocusFraction: values.focusScatterDepthOfFocusFraction, bokeh };
198
240
  const fisheye = lens.kind === "fisheye";
199
241
  return Object.freeze({ lensId: lens.lensId, name: lens.name, set: lens.set, kind: lens.kind, equivalentFocalLengthMm: lens.equivalentFocalLengthMm, focalLengthMm,
200
242
  cropFactor35Mm: crop, halfDiagonalMm, widestFNumber: lens.widestFNumber, narrowestFNumber: lens.narrowestFNumber,