@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
@@ -1 +1 @@
1
- {"version":3,"file":"system.js","sourceRoot":"","sources":["../../src/stabilization/system.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Generic image stabilization: profiles, disturbance trajectories, the stabilized rotation and its\n * effect on capture timing samples.\n *\n * The parsers validate untrusted input and return the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected.\n *\n * The generic stabilizer takes a declared angular disturbance (camera shake) and applies a per-axis\n * response, latency, travel limits and a panning policy. The leftover (residual) motion feeds the\n * existing temporal mapping. No commercial IBIS (in-body) or OIS (optical) calibration is supplied,\n * no arbitrary \"stops\" rating is used, and body/lens coordination is never inferred.\n * @see docs/STABILIZATION.md for the equations, units, coordinate conventions, known blockers and\n * support limits.\n */\n\nimport {\n approximationResult,\n type CalculationResult\n} from \"../core/calculation-result.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceBackedFact,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport {\n InvalidScientificInputError,\n requirePositiveInteger\n} from \"../core/validation.js\";\nimport type {\n RasterPoint\n} from \"../output/capture-geometry.js\";\nimport type {\n ResolvedCaptureModeTiming\n} from \"../sensor/capture-mode-timing.js\";\nimport { requireInputKeys, requireInputObject, rejectUnknownVariantFields, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, requireConfigFinite as requireFinite, parseConfigLimitations as parseLimitations, requireConfigFiniteAtLeastZero as requireNonNegativeFinite, requireConfigUnitInterval as requireFraction } from \"../core/record-validation.js\";\nimport { parseNonNegativeFact, parsePositiveFact } from \"../sensor/raw-readout.js\";\n\nexport const STABILIZATION_SYSTEM_PROFILE_SCHEMA_VERSION =\n \"0.1.0\" as const;\nexport const STABILIZATION_DISTURBANCE_TRAJECTORY_VERSION =\n \"0.1.0\" as const;\n\nexport type StabilizationRotationAxis =\n | \"pitch\"\n | \"yaw\"\n | \"roll\";\n\nexport type PhysicalStabilizationArchitecture =\n | \"off\"\n | \"sensor-shift\"\n | \"lens-optical\"\n | \"coordinated-physical\";\n\nexport type StabilizationCaptureKind =\n | \"still\"\n | \"video\";\n\nexport interface StabilizationAngularStateRad {\n pitch: number;\n yaw: number;\n roll: number;\n}\n\nexport interface StabilizationDisturbanceSample {\n timeSecondsFromCaptureReference:\n number;\n angularDisplacementRad:\n StabilizationAngularStateRad;\n}\n\nexport interface StabilizationDisturbanceTrajectory {\n version:\n typeof STABILIZATION_DISTURBANCE_TRAJECTORY_VERSION;\n trajectoryId: string;\n timeReference:\n \"first-opening-boundary-phase\";\n samples:\n readonly StabilizationDisturbanceSample[];\n initialAngularDisplacementIsZero:\n true;\n cameraTranslationIncluded:\n false;\n subjectMotionIncluded:\n false;\n supportStateEncoded:\n false;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface StabilizationAxisResponseProfile {\n axis: StabilizationRotationAxis;\n correctionGain:\n EvidenceBackedFact<number>;\n latencySeconds:\n EvidenceBackedFact<number>;\n maximumCorrectionAngleRad:\n EvidenceBackedFact<number>;\n}\n\nexport type StabilizationPanningPolicy =\n | {\n kind: \"none\";\n }\n | {\n kind:\n \"declared-axis-bypass\";\n axis:\n StabilizationRotationAxis;\n evidence:\n readonly EvidenceProvenance[];\n };\n\nexport interface StabilizationCoordinatedAllocation {\n bodyFraction: number;\n lensFraction: number;\n evidence: readonly EvidenceProvenance[];\n totalCorrectionAppliedOnce:\n true;\n}\n\nexport interface StabilizationSystemProfile {\n schemaVersion:\n typeof STABILIZATION_SYSTEM_PROFILE_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n profileKind:\n \"generic-synthetic\";\n scientificStatus:\n \"approximation\";\n architecture:\n PhysicalStabilizationArchitecture;\n captureKind:\n StabilizationCaptureKind;\n axisResponses:\n readonly StabilizationAxisResponseProfile[];\n panningPolicy:\n StabilizationPanningPolicy;\n coordinatedAllocation?:\n StabilizationCoordinatedAllocation;\n controlTransientModeled: false;\n spontaneousDriftModeled: false;\n cameraTranslationCorrectionModeled:\n false;\n digitalStabilizationIncluded:\n false;\n supportPolicyIncluded: false;\n stopRatingUsedAsDynamicResponse:\n false;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface CalculateStabilizedRotationTrajectoryInput {\n disturbance:\n StabilizationDisturbanceTrajectory;\n profile:\n StabilizationSystemProfile;\n captureKind:\n StabilizationCaptureKind;\n}\n\nexport interface StabilizationAxisResolution {\n axis: StabilizationRotationAxis;\n disturbanceAngleRad: number;\n delayedMeasuredAngleRad: number;\n requestedCorrectionAngleRad:\n number;\n appliedCorrectionAngleRad:\n number;\n residualAngleRad: number;\n correctionGain: number;\n latencySeconds: number;\n maximumCorrectionAngleRad:\n number;\n bypassedForDeclaredPan:\n boolean;\n correctionLimitReached:\n boolean;\n}\n\nexport interface StabilizedRotationSample {\n timeSecondsFromCaptureReference:\n number;\n disturbanceAngularDisplacementRad:\n StabilizationAngularStateRad;\n appliedCorrectionAngularDisplacementRad:\n StabilizationAngularStateRad;\n residualAngularDisplacementRad:\n StabilizationAngularStateRad;\n axes:\n readonly StabilizationAxisResolution[];\n}\n\nexport interface StabilizedRotationTrajectory {\n profileId: string;\n profileVersion: string;\n trajectoryId: string;\n architecture:\n PhysicalStabilizationArchitecture;\n captureKind:\n StabilizationCaptureKind;\n timeReference:\n \"first-opening-boundary-phase\";\n samples:\n readonly StabilizedRotationSample[];\n correctionModel:\n \"delayed-linear-image-equivalent-angular-response\";\n supportStateConsumed: false;\n translationCorrectionModeled:\n false;\n digitalStabilizationApplied:\n false;\n digitalStabilizationOwnedBy:\n \"downstream-geometric-correction-composition\";\n coordinatedCorrectionDoubleCounted:\n false;\n zeroDisturbanceCanCreateMotion:\n false;\n}\n\nexport interface CalculateStabilizedCaptureTemporalSamplesInput {\n disturbance:\n StabilizationDisturbanceTrajectory;\n profile:\n StabilizationSystemProfile;\n captureKind:\n StabilizationCaptureKind;\n timing:\n ResolvedCaptureModeTiming;\n samplePointsNative:\n readonly RasterPoint[];\n temporalSampleCount: number;\n}\n\nexport interface StabilizedCaptureTemporalNode {\n temporalSampleIndex: number;\n localExposurePhase: number;\n captureTimeSecondsFromReference:\n number;\n normalizedTimeWeight: number;\n timeMeasureSeconds: number;\n stabilization:\n StabilizedRotationSample;\n}\n\nexport interface StabilizedCaptureTemporalPoint {\n destinationPointNative:\n RasterPoint;\n localExposureWindow: {\n startSecondsFromCaptureReference:\n number;\n endSecondsFromCaptureReference:\n number;\n durationSeconds: number;\n };\n nodes:\n readonly StabilizedCaptureTemporalNode[];\n}\n\nexport interface StabilizedCaptureTemporalSamples {\n profileId: string;\n trajectoryId: string;\n captureModeId: string;\n timingProfileId: string;\n captureKind:\n StabilizationCaptureKind;\n architecture:\n PhysicalStabilizationArchitecture;\n timeReference:\n \"first-opening-boundary-phase\";\n quadratureScheme:\n \"uniform-midpoint\";\n temporalSampleCount: number;\n points:\n readonly StabilizedCaptureTemporalPoint[];\n sensorReadoutTimingUsedAsExposureTiming:\n false;\n supportStateConsumed: false;\n translationCorrectionModeled:\n false;\n digitalStabilizationApplied:\n false;\n}\n\nconst AXES =\n new Set<StabilizationRotationAxis>([\n \"pitch\",\n \"yaw\",\n \"roll\"\n ]);\n\nconst ARCHITECTURES =\n new Set<PhysicalStabilizationArchitecture>([\n \"off\",\n \"sensor-shift\",\n \"lens-optical\",\n \"coordinated-physical\"\n ]);\n\nconst CAPTURE_KINDS =\n new Set<StabilizationCaptureKind>([\n \"still\",\n \"video\"\n ]);\n\nfunction parseFractionFact(\n value: unknown,\n path: string\n): EvidenceBackedFact<number> {\n const record =\n requireRecord(value, path, [\"value\", \"evidence\"]);\n return {\n value:\n requireFraction(\n record.value,\n path + \".value\"\n ),\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\nfunction parseAxis(\n value: unknown,\n path: string\n): StabilizationRotationAxis {\n if (\n typeof value !== \"string\" ||\n !AXES.has(\n value as\n StabilizationRotationAxis\n )\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value as\n StabilizationRotationAxis;\n}\n\nfunction parseAxisResponse(\n value: unknown,\n path: string\n): StabilizationAxisResponseProfile {\n const record =\n requireRecord(value, path, [\"axis\", \"correctionGain\", \"latencySeconds\", \"maximumCorrectionAngleRad\"]);\n return {\n axis:\n parseAxis(\n record.axis,\n path + \".axis\"\n ),\n correctionGain:\n parseFractionFact(\n record.correctionGain,\n path +\n \".correctionGain\"\n ),\n latencySeconds:\n parseNonNegativeFact(\n record.latencySeconds,\n path +\n \".latencySeconds\"\n ),\n maximumCorrectionAngleRad:\n parsePositiveFact(\n record\n .maximumCorrectionAngleRad,\n path +\n \".maximumCorrectionAngleRad\"\n )\n };\n}\n\nfunction parsePanningPolicy(\n value: unknown,\n path: string\n): StabilizationPanningPolicy {\n const record =\n requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", { none: [\"kind\"], \"declared-axis-bypass\": [\"kind\", \"axis\", \"evidence\"] }, path);\n if (record.kind === \"none\") {\n return {\n kind: \"none\"\n };\n }\n if (\n record.kind ===\n \"declared-axis-bypass\"\n ) {\n return {\n kind:\n \"declared-axis-bypass\",\n axis:\n parseAxis(\n record.axis,\n path + \".axis\"\n ),\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n }\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseCoordinatedAllocation(\n value: unknown,\n path: string\n): StabilizationCoordinatedAllocation {\n const record =\n requireRecord(value, path, [\"totalCorrectionAppliedOnce\", \"bodyFraction\", \"lensFraction\", \"evidence\"]);\n if (\n record\n .totalCorrectionAppliedOnce !==\n true\n ) {\n throw new InvalidConfigurationError(\n path +\n \".totalCorrectionAppliedOnce must be true.\"\n );\n }\n const bodyFraction =\n requireFraction(\n record.bodyFraction,\n path + \".bodyFraction\"\n );\n const lensFraction =\n requireFraction(\n record.lensFraction,\n path + \".lensFraction\"\n );\n if (\n Math.abs(\n bodyFraction +\n lensFraction -\n 1\n ) >\n 1e-12\n ) {\n throw new InvalidConfigurationError(\n path +\n \" bodyFraction + lensFraction must equal one.\"\n );\n }\n return {\n bodyFraction,\n lensFraction,\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n ),\n totalCorrectionAppliedOnce:\n true\n };\n}\n\n/**\n * Validates an untrusted declaration and returns the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected here.\n *\n * The generic stabilizer takes a declared angular disturbance (camera shake) and applies a per-axis\n * response, latency, travel limits and a panning policy. The leftover (residual) motion feeds the\n * existing temporal mapping. No commercial IBIS (in-body) or OIS (optical) calibration is supplied,\n * no arbitrary \"stops\" rating is used, and body/lens coordination is never inferred.\n * @param value - unknown. Untrusted input; TypeScript types alone are not validation.\n * @returns StabilizationSystemProfile. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function parseStabilizationSystemProfile(\n value: unknown\n): StabilizationSystemProfile {\n const record =\n requireRecord(\n value,\n \"stabilizationSystemProfile\", [\"schemaVersion\", \"profileKind\", \"scientificStatus\", \"architecture\", \"captureKind\", \"axisResponses\", \"panningPolicy\", \"coordinatedAllocation\", \"profileId\", \"profileVersion\", \"evidence\", \"limitations\", \"controlTransientModeled\", \"spontaneousDriftModeled\", \"cameraTranslationCorrectionModeled\", \"digitalStabilizationIncluded\", \"supportPolicyIncluded\", \"stopRatingUsedAsDynamicResponse\"]\n );\n if (\n record.schemaVersion !==\n STABILIZATION_SYSTEM_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'stabilizationSystemProfile.schemaVersion must be \"' +\n STABILIZATION_SYSTEM_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n if (\n record.profileKind !==\n \"generic-synthetic\" ||\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n 'stabilizationSystemProfile schema 0.1.0 requires profileKind \"generic-synthetic\" and scientificStatus \"approximation\".'\n );\n }\n if (\n typeof record.architecture !==\n \"string\" ||\n !ARCHITECTURES.has(\n record.architecture as\n PhysicalStabilizationArchitecture\n )\n ) {\n throw new InvalidConfigurationError(\n \"stabilizationSystemProfile.architecture is invalid.\"\n );\n }\n if (\n typeof record.captureKind !==\n \"string\" ||\n !CAPTURE_KINDS.has(\n record.captureKind as\n StabilizationCaptureKind\n )\n ) {\n throw new InvalidConfigurationError(\n \"stabilizationSystemProfile.captureKind is invalid.\"\n );\n }\n\n for (\n const key of [\n \"controlTransientModeled\",\n \"spontaneousDriftModeled\",\n \"cameraTranslationCorrectionModeled\",\n \"digitalStabilizationIncluded\",\n \"supportPolicyIncluded\",\n \"stopRatingUsedAsDynamicResponse\"\n ] as const\n ) {\n if (record[key] !== false) {\n throw new InvalidConfigurationError(\n \"stabilizationSystemProfile.\" +\n key +\n \" must be false in schema 0.1.0.\"\n );\n }\n }\n\n if (\n !Array.isArray(\n record.axisResponses\n )\n ) {\n throw new InvalidConfigurationError(\n \"stabilizationSystemProfile.axisResponses must be an array.\"\n );\n }\n const axisResponses =\n record.axisResponses.map(\n (entry, index) =>\n parseAxisResponse(\n entry,\n \"stabilizationSystemProfile.axisResponses[\" +\n index +\n \"]\"\n )\n );\n const axes =\n axisResponses.map(\n (entry) =>\n entry.axis\n );\n if (\n new Set(axes).size !==\n axes.length\n ) {\n throw new InvalidConfigurationError(\n \"stabilizationSystemProfile.axisResponses must not contain duplicate axes.\"\n );\n }\n\n const architecture =\n record.architecture as\n PhysicalStabilizationArchitecture;\n if (\n architecture === \"off\" &&\n axisResponses.length !== 0\n ) {\n throw new InvalidConfigurationError(\n \"An off stabilization profile must not declare axis responses.\"\n );\n }\n if (\n architecture !== \"off\" &&\n axisResponses.length === 0\n ) {\n throw new InvalidConfigurationError(\n \"An enabled physical stabilization profile must declare at least one axis response.\"\n );\n }\n\n const panningPolicy =\n parsePanningPolicy(\n record.panningPolicy,\n \"stabilizationSystemProfile.panningPolicy\"\n );\n if (\n architecture === \"off\" &&\n panningPolicy.kind !== \"none\"\n ) {\n throw new InvalidConfigurationError(\n \"An off stabilization profile must use panningPolicy.kind \\\"none\\\".\"\n );\n }\n if (\n panningPolicy.kind ===\n \"declared-axis-bypass\" &&\n !axisResponses.some(\n (entry) =>\n entry.axis ===\n panningPolicy.axis\n )\n ) {\n throw new InvalidConfigurationError(\n \"Declared panning bypass axis must exist in axisResponses.\"\n );\n }\n\n const coordinatedAllocation =\n record.coordinatedAllocation ===\n undefined\n ? undefined\n : parseCoordinatedAllocation(\n record.coordinatedAllocation,\n \"stabilizationSystemProfile.coordinatedAllocation\"\n );\n if (\n architecture ===\n \"coordinated-physical\" &&\n coordinatedAllocation ===\n undefined\n ) {\n throw new InvalidConfigurationError(\n \"Coordinated physical stabilization requires an explicit body/lens correction allocation.\"\n );\n }\n if (\n architecture !==\n \"coordinated-physical\" &&\n coordinatedAllocation !==\n undefined\n ) {\n throw new InvalidConfigurationError(\n \"Only coordinated physical stabilization may declare coordinatedAllocation.\"\n );\n }\n\n return {\n schemaVersion:\n STABILIZATION_SYSTEM_PROFILE_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"stabilizationSystemProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"stabilizationSystemProfile.profileVersion\"\n ),\n profileKind:\n \"generic-synthetic\",\n scientificStatus:\n \"approximation\",\n architecture,\n captureKind:\n record.captureKind as\n StabilizationCaptureKind,\n axisResponses,\n panningPolicy,\n ...(coordinatedAllocation ===\n undefined\n ? {}\n : {\n coordinatedAllocation\n }),\n controlTransientModeled:\n false,\n spontaneousDriftModeled:\n false,\n cameraTranslationCorrectionModeled:\n false,\n digitalStabilizationIncluded:\n false,\n supportPolicyIncluded:\n false,\n stopRatingUsedAsDynamicResponse:\n false,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"stabilizationSystemProfile.evidence\"\n ),\n limitations:\n parseLimitations(\n record.limitations,\n \"stabilizationSystemProfile.limitations\"\n )\n };\n}\n\nfunction parseAngularState(\n value: unknown,\n path: string\n): StabilizationAngularStateRad {\n const record =\n requireRecord(value, path, [\"pitch\", \"yaw\", \"roll\"]);\n return {\n pitch:\n requireFinite(\n record.pitch,\n path + \".pitch\"\n ),\n yaw:\n requireFinite(\n record.yaw,\n path + \".yaw\"\n ),\n roll:\n requireFinite(\n record.roll,\n path + \".roll\"\n )\n };\n}\n\n/**\n * Validates an untrusted declaration and returns the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected here.\n *\n * The generic stabilizer takes a declared angular disturbance (camera shake) and applies a per-axis\n * response, latency, travel limits and a panning policy. The leftover (residual) motion feeds the\n * existing temporal mapping. No commercial IBIS (in-body) or OIS (optical) calibration is supplied,\n * no arbitrary \"stops\" rating is used, and body/lens coordination is never inferred.\n * @param value - unknown. Untrusted input; TypeScript types alone are not validation.\n * @returns StabilizationDisturbanceTrajectory. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function parseStabilizationDisturbanceTrajectory(\n value: unknown\n): StabilizationDisturbanceTrajectory {\n const record =\n requireRecord(\n value,\n \"stabilizationDisturbanceTrajectory\", [\"version\", \"timeReference\", \"initialAngularDisplacementIsZero\", \"cameraTranslationIncluded\", \"subjectMotionIncluded\", \"supportStateEncoded\", \"samples\", \"trajectoryId\", \"evidence\", \"limitations\"]\n );\n if (\n record.version !==\n STABILIZATION_DISTURBANCE_TRAJECTORY_VERSION ||\n record.timeReference !==\n \"first-opening-boundary-phase\" ||\n record\n .initialAngularDisplacementIsZero !==\n true ||\n record\n .cameraTranslationIncluded !==\n false ||\n record.subjectMotionIncluded !==\n false ||\n record.supportStateEncoded !==\n false\n ) {\n throw new InvalidConfigurationError(\n \"stabilizationDisturbanceTrajectory metadata is invalid for version 0.1.0.\"\n );\n }\n if (\n !Array.isArray(record.samples) ||\n record.samples.length < 2\n ) {\n throw new InvalidConfigurationError(\n \"stabilizationDisturbanceTrajectory.samples must contain at least two samples.\"\n );\n }\n\n let previousTime =\n Number.NEGATIVE_INFINITY;\n const samples =\n record.samples.map(\n (entry, index) => {\n const path =\n \"stabilizationDisturbanceTrajectory.samples[\" +\n index +\n \"]\";\n const sample =\n requireRecord(\n entry,\n path, [\"timeSecondsFromCaptureReference\", \"angularDisplacementRad\"]\n );\n const time =\n requireNonNegativeFinite(\n sample\n .timeSecondsFromCaptureReference,\n path +\n \".timeSecondsFromCaptureReference\"\n );\n if (time <= previousTime) {\n throw new InvalidConfigurationError(\n \"stabilizationDisturbanceTrajectory sample times must be strictly increasing.\"\n );\n }\n previousTime = time;\n return {\n timeSecondsFromCaptureReference:\n time,\n angularDisplacementRad:\n parseAngularState(\n sample\n .angularDisplacementRad,\n path +\n \".angularDisplacementRad\"\n )\n };\n }\n );\n\n const first =\n samples[0]!;\n if (\n first\n .timeSecondsFromCaptureReference !==\n 0 ||\n first\n .angularDisplacementRad\n .pitch !== 0 ||\n first\n .angularDisplacementRad\n .yaw !== 0 ||\n first\n .angularDisplacementRad\n .roll !== 0\n ) {\n throw new InvalidConfigurationError(\n \"stabilizationDisturbanceTrajectory must begin at capture-reference t=0 with zero angular displacement.\"\n );\n }\n\n return {\n version:\n STABILIZATION_DISTURBANCE_TRAJECTORY_VERSION,\n trajectoryId:\n requireNonEmptyString(\n record.trajectoryId,\n \"stabilizationDisturbanceTrajectory.trajectoryId\"\n ),\n timeReference:\n \"first-opening-boundary-phase\",\n samples,\n initialAngularDisplacementIsZero:\n true,\n cameraTranslationIncluded:\n false,\n subjectMotionIncluded:\n false,\n supportStateEncoded:\n false,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"stabilizationDisturbanceTrajectory.evidence\"\n ),\n limitations:\n parseLimitations(\n record.limitations,\n \"stabilizationDisturbanceTrajectory.limitations\"\n )\n };\n}\n\n/**\n * Lookup index over a parsed disturbance trajectory, built for evaluation. Support times are copied\n * once into a Float64Array (exact IEEE-754 values). Each lookup is then an O(log n) binary search\n * instead of an O(n) scan. The interpolation arithmetic is unchanged.\n */\ninterface DisturbanceIndex {\n readonly samples:\n StabilizationDisturbanceTrajectory[\"samples\"];\n readonly times: Float64Array;\n}\n\nfunction indexDisturbance(\n trajectory:\n StabilizationDisturbanceTrajectory\n): DisturbanceIndex {\n const times =\n new Float64Array(\n trajectory.samples.length\n );\n for (\n let index = 0;\n index < times.length;\n index += 1\n ) {\n times[index] =\n trajectory.samples[index]!\n .timeSecondsFromCaptureReference;\n }\n return {\n samples:\n trajectory.samples,\n times\n };\n}\n\n/**\n * Returns the left index of the support segment used for `timeSeconds`. Returns -1 for the final support\n * time, which uses its stored value. The chosen segment is exactly the one a first-match linear scan\n * would pick: the smallest `i` with `t[i] <= timeSeconds <= t[i + 1]`. Support times strictly\n * increase, so a time that equals an interior support time uses the segment on its left.\n */\nfunction locateDisturbanceSegment(\n disturbance: DisturbanceIndex,\n timeSeconds: number\n): number {\n const times =\n disturbance.times;\n const lastIndex =\n times.length - 1;\n if (\n timeSeconds < times[0]! ||\n timeSeconds > times[lastIndex]!\n ) {\n throw new InvalidScientificInputError(\n \"Requested stabilization evaluation time lies outside the disturbance trajectory support.\"\n );\n }\n\n if (\n timeSeconds ===\n times[lastIndex]!\n ) {\n return -1;\n }\n\n // Lower bound: first index whose support time is >= timeSeconds.\n let low = 0;\n let high = lastIndex;\n while (low < high) {\n const middle =\n (low + high) >>> 1;\n if (\n times[middle]! >=\n timeSeconds\n ) {\n high = middle;\n } else {\n low = middle + 1;\n }\n }\n const index =\n low === 0 ? 0 : low - 1;\n if (\n !(\n timeSeconds >=\n times[index]! &&\n timeSeconds <=\n times[index + 1]!\n )\n ) {\n throw new InvalidScientificInputError(\n \"Disturbance trajectory interpolation failed.\"\n );\n }\n return index;\n}\n\nfunction interpolateDisturbanceSegment(\n disturbance: DisturbanceIndex,\n segmentIndex: number,\n timeSeconds: number,\n axis:\n StabilizationRotationAxis\n): number {\n const samples =\n disturbance.samples;\n if (segmentIndex < 0) {\n return samples[\n samples.length - 1\n ]!\n .angularDisplacementRad[\n axis\n ];\n }\n const left =\n samples[segmentIndex]!;\n const right =\n samples[\n segmentIndex + 1\n ]!;\n const duration =\n right\n .timeSecondsFromCaptureReference -\n left\n .timeSecondsFromCaptureReference;\n const phase =\n duration === 0\n ? 0\n : (\n timeSeconds -\n left\n .timeSecondsFromCaptureReference\n ) /\n duration;\n const a =\n left\n .angularDisplacementRad[\n axis\n ];\n const b =\n right\n .angularDisplacementRad[\n axis\n ];\n return (\n a +\n (b - a) * phase\n );\n}\n\nfunction interpolateAxis(\n disturbance: DisturbanceIndex,\n timeSeconds: number,\n axis:\n StabilizationRotationAxis\n): number {\n return interpolateDisturbanceSegment(\n disturbance,\n locateDisturbanceSegment(\n disturbance,\n timeSeconds\n ),\n timeSeconds,\n axis\n );\n}\n\nfunction axisValue(\n state:\n StabilizationAngularStateRad,\n axis:\n StabilizationRotationAxis\n): number {\n return state[axis];\n}\n\nfunction setAxisValue(\n state:\n StabilizationAngularStateRad,\n axis:\n StabilizationRotationAxis,\n value: number\n): void {\n state[axis] = value;\n}\n\nfunction clampSymmetric(\n value: number,\n limit: number\n): number {\n return Math.max(\n -limit,\n Math.min(limit, value)\n );\n}\n\ntype AxisResponseIndex = ReadonlyMap<\n StabilizationRotationAxis,\n StabilizationSystemProfile[\"axisResponses\"][number]\n>;\n\n/** Built once per calculation. Later entries win, as with a per-evaluation Map. */\nfunction indexAxisResponses(\n profile:\n StabilizationSystemProfile\n): AxisResponseIndex {\n return new Map(\n profile.axisResponses.map(\n (response) => [\n response.axis,\n response\n ] as const\n )\n );\n}\n\nfunction evaluateAtTime(\n disturbance: DisturbanceIndex,\n profile:\n StabilizationSystemProfile,\n responses: AxisResponseIndex,\n timeSeconds: number\n): StabilizedRotationSample {\n // One segment lookup serves all three axes at the same time.\n const segment =\n locateDisturbanceSegment(\n disturbance,\n timeSeconds\n );\n const current:\n StabilizationAngularStateRad = {\n pitch:\n interpolateDisturbanceSegment(\n disturbance,\n segment,\n timeSeconds,\n \"pitch\"\n ),\n yaw:\n interpolateDisturbanceSegment(\n disturbance,\n segment,\n timeSeconds,\n \"yaw\"\n ),\n roll:\n interpolateDisturbanceSegment(\n disturbance,\n segment,\n timeSeconds,\n \"roll\"\n )\n };\n const correction:\n StabilizationAngularStateRad = {\n pitch: 0,\n yaw: 0,\n roll: 0\n };\n const residual:\n StabilizationAngularStateRad = {\n ...current\n };\n\n const axes =\n [\"pitch\", \"yaw\", \"roll\"] as const;\n const resolvedAxes =\n axes.map((axis) => {\n const response =\n responses.get(axis);\n const bypassed =\n profile.panningPolicy.kind ===\n \"declared-axis-bypass\" &&\n profile.panningPolicy.axis ===\n axis;\n\n if (\n profile.architecture ===\n \"off\" ||\n response === undefined ||\n bypassed\n ) {\n return {\n axis,\n disturbanceAngleRad:\n axisValue(\n current,\n axis\n ),\n delayedMeasuredAngleRad:\n 0,\n requestedCorrectionAngleRad:\n 0,\n appliedCorrectionAngleRad:\n 0,\n residualAngleRad:\n axisValue(\n current,\n axis\n ),\n correctionGain:\n response?.correctionGain\n .value ?? 0,\n latencySeconds:\n response?.latencySeconds\n .value ?? 0,\n maximumCorrectionAngleRad:\n response\n ?.maximumCorrectionAngleRad\n .value ?? 0,\n bypassedForDeclaredPan:\n bypassed,\n correctionLimitReached:\n false\n };\n }\n\n const delayedTime =\n timeSeconds -\n response\n .latencySeconds.value;\n const delayedMeasured =\n delayedTime < 0\n ? 0\n : interpolateAxis(\n disturbance,\n delayedTime,\n axis\n );\n const requested =\n delayedMeasured *\n response\n .correctionGain.value;\n const applied =\n clampSymmetric(\n requested,\n response\n .maximumCorrectionAngleRad\n .value\n );\n const residualAngle =\n axisValue(\n current,\n axis\n ) -\n applied;\n\n setAxisValue(\n correction,\n axis,\n applied\n );\n setAxisValue(\n residual,\n axis,\n residualAngle\n );\n\n return {\n axis,\n disturbanceAngleRad:\n axisValue(\n current,\n axis\n ),\n delayedMeasuredAngleRad:\n delayedMeasured,\n requestedCorrectionAngleRad:\n requested,\n appliedCorrectionAngleRad:\n applied,\n residualAngleRad:\n residualAngle,\n correctionGain:\n response\n .correctionGain.value,\n latencySeconds:\n response\n .latencySeconds.value,\n maximumCorrectionAngleRad:\n response\n .maximumCorrectionAngleRad\n .value,\n bypassedForDeclaredPan:\n false,\n correctionLimitReached:\n applied !== requested\n };\n });\n\n return {\n timeSecondsFromCaptureReference:\n timeSeconds,\n disturbanceAngularDisplacementRad:\n current,\n appliedCorrectionAngularDisplacementRad:\n correction,\n residualAngularDisplacementRad:\n residual,\n axes:\n resolvedAxes\n };\n}\n\n/**\n * Runs the declared generic per-axis controller against an explicit angular disturbance trajectory.\n * Returns the residual motion, with diagnostics for latency and travel limits.\n *\n * The generic stabilizer takes a declared angular disturbance (camera shake) and applies a per-axis\n * response, latency, travel limits and a panning policy. The leftover (residual) motion feeds the\n * existing temporal mapping. No commercial IBIS (in-body) or OIS (optical) calibration is supplied,\n * no arbitrary \"stops\" rating is used, and body/lens coordination is never inferred.\n * @param input - CalculateStabilizedRotationTrajectoryInput. See that type for coordinates, units and profile binding.\n * @returns CalculationResult<StabilizedRotationTrajectory>. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function calculateStabilizedRotationTrajectory(\n input:\n CalculateStabilizedRotationTrajectoryInput\n): CalculationResult<StabilizedRotationTrajectory> {\n requireInputKeys(input, \"calculateStabilizedRotationTrajectory\", [\"disturbance\", \"profile\", \"captureKind\"]);\n const disturbance =\n parseStabilizationDisturbanceTrajectory(\n input.disturbance\n );\n const profile =\n parseStabilizationSystemProfile(\n input.profile\n );\n\n if (\n input.captureKind !==\n profile.captureKind\n ) {\n throw new InvalidScientificInputError(\n \"captureKind must exactly match the stabilization profile captureKind.\"\n );\n }\n\n const disturbanceIndex =\n indexDisturbance(disturbance);\n const responses =\n indexAxisResponses(profile);\n const samples =\n disturbance.samples.map(\n (sample) =>\n evaluateAtTime(\n disturbanceIndex,\n profile,\n responses,\n sample\n .timeSecondsFromCaptureReference\n )\n );\n\n return approximationResult(\n {\n profileId:\n profile.profileId,\n profileVersion:\n profile.profileVersion,\n trajectoryId:\n disturbance.trajectoryId,\n architecture:\n profile.architecture,\n captureKind:\n input.captureKind,\n timeReference:\n \"first-opening-boundary-phase\",\n samples,\n correctionModel:\n \"delayed-linear-image-equivalent-angular-response\",\n supportStateConsumed:\n false,\n translationCorrectionModeled:\n false,\n digitalStabilizationApplied:\n false,\n digitalStabilizationOwnedBy:\n \"downstream-geometric-correction-composition\",\n coordinatedCorrectionDoubleCounted:\n false,\n zeroDisturbanceCanCreateMotion:\n false\n },\n \"generic-time-domain-physical-stabilization\",\n \"1.0.0\",\n [\n \"The stabilization response is a generic synthetic image-equivalent rotational correction, not a manufacturer-specific IBIS/OIS calibration.\",\n \"Correction uses explicit per-axis gain, latency and symmetric angular correction limits.\",\n \"A coordinated profile allocates one total correction between body and lens for descriptive ownership only; the total correction is applied once.\",\n \"Support state is not an input and never silently toggles stabilization.\",\n \"Declared panning bypass suppresses correction only on the explicitly selected axis; pan intent is never inferred.\",\n \"Camera translation/parallax correction is not modeled because translational image motion depends on scene depth.\",\n \"Digital stabilization is a separate downstream geometric/crop/resampling domain.\",\n \"CIPA-style stop ratings are not used as a dynamic response function.\",\n \"The legacy stabilizationStopsEquivalent approximation remains unchanged.\"\n ]\n );\n}\n\ntype ExposureWindowSample =\n ResolvedCaptureModeTiming[\"exposureWindows\"][\"samples\"][number];\ntype ExposureWindowIndex = ReadonlyMap<\n unknown,\n ReadonlyMap<unknown, readonly ExposureWindowSample[]>\n>;\n\n/**\n * Groups the committed exposure-window samples by native point, once per calculation, and keeps their\n * order. Map keys compare with SameValueZero, so lookups are filtered again with the original `===`\n * test: NaN never matches, and +0 matches -0.\n */\nfunction indexExposureWindows(\n timing:\n ResolvedCaptureModeTiming\n): ExposureWindowIndex {\n requireInputObject(timing, \"timing\");\n requireInputObject(timing.exposureWindows, \"timing.exposureWindows\");\n if (!Array.isArray(timing.exposureWindows.samples)) throw new InvalidConfigurationError(\"timing.exposureWindows.samples must be an array.\");\n timing.exposureWindows.samples.forEach((sample, index) => {\n requireInputObject(sample, \"timing.exposureWindows.samples[\" + index + \"]\");\n requireInputObject(sample.pointNative, \"timing.exposureWindows.samples[\" + index + \"].pointNative\");\n });\n const byX =\n new Map<\n unknown,\n Map<unknown, ExposureWindowSample[]>\n >();\n for (const sample of timing.exposureWindows.samples) {\n let byY =\n byX.get(sample.pointNative.x);\n if (byY === undefined) {\n byY = new Map();\n byX.set(\n sample.pointNative.x,\n byY\n );\n }\n const bucket =\n byY.get(sample.pointNative.y);\n if (bucket === undefined) {\n byY.set(\n sample.pointNative.y,\n [sample]\n );\n } else {\n bucket.push(sample);\n }\n }\n return byX;\n}\n\nfunction localExposureForPoint(\n windows: ExposureWindowIndex,\n point:\n RasterPoint\n): {\n start: number;\n end: number;\n duration: number;\n} {\n const matches =\n (\n windows\n .get(point.x)\n ?.get(point.y) ?? []\n ).filter(\n (sample) =>\n sample.pointNative.x ===\n point.x &&\n sample.pointNative.y ===\n point.y\n );\n if (matches.length !== 1) {\n throw new InvalidScientificInputError(\n \"Each stabilization sample point must match exactly one committed exposure-window sample point.\"\n );\n }\n const match =\n matches[0]!;\n return {\n start:\n match\n .startOffsetSecondsFromOpeningReference,\n end:\n match\n .endOffsetSecondsFromOpeningReference,\n duration:\n match\n .localExposureDurationSeconds\n };\n}\n\n/**\n * Feeds the residual stabilized rotation into the existing local-exposure temporal mapping. Shutter\n * timing is not changed, and no blur radius is invented.\n *\n * The generic stabilizer takes a declared angular disturbance (camera shake) and applies a per-axis\n * response, latency, travel limits and a panning policy. The leftover (residual) motion feeds the\n * existing temporal mapping. No commercial IBIS (in-body) or OIS (optical) calibration is supplied,\n * no arbitrary \"stops\" rating is used, and body/lens coordination is never inferred.\n * @param input - CalculateStabilizedCaptureTemporalSamplesInput. See that type for coordinates, units and profile binding.\n * @returns CalculationResult<StabilizedCaptureTemporalSamples>. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function calculateStabilizedCaptureTemporalSamples(\n input:\n CalculateStabilizedCaptureTemporalSamplesInput\n): CalculationResult<StabilizedCaptureTemporalSamples> {\n requireInputKeys(input, \"calculateStabilizedCaptureTemporalSamples\", [\"disturbance\", \"profile\", \"captureKind\", \"timing\", \"samplePointsNative\", \"temporalSampleCount\"]);\n requireInputObject(input.timing, \"timing\");\n const disturbance =\n parseStabilizationDisturbanceTrajectory(\n input.disturbance\n );\n const profile =\n parseStabilizationSystemProfile(\n input.profile\n );\n if (\n input.captureKind !==\n profile.captureKind\n ) {\n throw new InvalidScientificInputError(\n \"captureKind must exactly match the stabilization profile captureKind.\"\n );\n }\n requirePositiveInteger(\n \"temporalSampleCount\",\n input.temporalSampleCount\n );\n if (\n !Array.isArray(\n input.samplePointsNative\n ) ||\n input.samplePointsNative.length ===\n 0\n ) {\n throw new InvalidConfigurationError(\n \"samplePointsNative must be a non-empty array.\"\n );\n }\n input.samplePointsNative.forEach((point, index) => requireInputObject(point, \"samplePointsNative[\" + index + \"]\"));\n\n const totalNodeCount =\n input.temporalSampleCount *\n input.samplePointsNative.length;\n if (\n !Number.isSafeInteger(\n totalNodeCount\n )\n ) {\n throw new InvalidScientificInputError(\n \"temporalSampleCount × samplePointsNative.length must remain a safe integer.\"\n );\n }\n\n const disturbanceIndex =\n indexDisturbance(disturbance);\n const responses =\n indexAxisResponses(profile);\n let exposureWindowIndex:\n ExposureWindowIndex | undefined;\n const points =\n input.samplePointsNative.map(\n (point) => {\n exposureWindowIndex ??=\n indexExposureWindows(\n input.timing\n );\n const exposure =\n localExposureForPoint(\n exposureWindowIndex,\n point\n );\n const normalizedTimeWeight =\n 1 /\n input.temporalSampleCount;\n const timeMeasureSeconds =\n exposure.duration /\n input.temporalSampleCount;\n\n const nodes =\n Array.from(\n {\n length:\n input.temporalSampleCount\n },\n (\n _,\n temporalSampleIndex\n ) => {\n const localExposurePhase =\n (\n temporalSampleIndex +\n 0.5\n ) /\n input.temporalSampleCount;\n const captureTime =\n exposure.start +\n localExposurePhase *\n exposure.duration;\n return {\n temporalSampleIndex,\n localExposurePhase,\n captureTimeSecondsFromReference:\n captureTime,\n normalizedTimeWeight,\n timeMeasureSeconds,\n stabilization:\n evaluateAtTime(\n disturbanceIndex,\n profile,\n responses,\n captureTime\n )\n };\n }\n );\n\n return {\n destinationPointNative: {\n ...point\n },\n localExposureWindow: {\n startSecondsFromCaptureReference:\n exposure.start,\n endSecondsFromCaptureReference:\n exposure.end,\n durationSeconds:\n exposure.duration\n },\n nodes\n };\n }\n );\n\n return approximationResult(\n {\n profileId:\n profile.profileId,\n trajectoryId:\n disturbance.trajectoryId,\n captureModeId:\n input.timing.captureModeId,\n timingProfileId:\n input.timing.timingProfileId,\n captureKind:\n input.captureKind,\n architecture:\n profile.architecture,\n timeReference:\n \"first-opening-boundary-phase\",\n quadratureScheme:\n \"uniform-midpoint\",\n temporalSampleCount:\n input.temporalSampleCount,\n points,\n sensorReadoutTimingUsedAsExposureTiming:\n false,\n supportStateConsumed:\n false,\n translationCorrectionModeled:\n false,\n digitalStabilizationApplied:\n false\n },\n \"capture-local-stabilization-temporal-sampling\",\n \"1.0.0\",\n [\n \"Stabilization is evaluated at deterministic midpoint nodes inside each authoritative local exposure window of the exposure-window model.\",\n \"Sensor data-readout timing is not substituted for exposure timing.\",\n \"The result is rotational disturbance/correction/residual state only; it does not itself calculate image-plane mapping, radiance, blur, PSF or output pixels.\",\n \"Translation/parallax, subject motion, shutter shock, support vibration sources and digital stabilization remain separate domains.\"\n ]\n );\n}\n"]}
1
+ {"version":3,"file":"system.js","sourceRoot":"","sources":["../../src/stabilization/system.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Generic image stabilization: profiles, disturbance trajectories, the stabilized rotation and its\n * effect on capture timing samples.\n *\n * The parsers validate untrusted input and return the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected.\n *\n * The generic stabilizer takes a declared angular disturbance (camera shake) and applies a per-axis\n * response, latency, travel limits and a panning policy. The leftover (residual) motion feeds the\n * existing temporal mapping. No commercial IBIS (in-body) or OIS (optical) calibration is supplied,\n * no arbitrary \"stops\" rating is used, and body/lens coordination is never inferred.\n * @see docs/STABILIZATION.md for the equations, units, coordinate conventions, known blockers and\n * support limits.\n */\n\nimport {\n approximationResult,\n type CalculationResult\n} from \"../core/calculation-result.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceBackedFact,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport {\n InvalidScientificInputError,\n requirePositiveInteger\n} from \"../core/validation.js\";\nimport type {\n RasterPoint\n} from \"../output/capture-geometry.js\";\nimport type {\n ResolvedCaptureModeTiming\n} from \"../sensor/capture-mode-timing.js\";\nimport { requireInputKeys, requireInputObject, rejectUnknownVariantFields, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, requireConfigFinite as requireFinite, parseConfigLimitations as parseLimitations, requireConfigFiniteAtLeastZero as requireNonNegativeFinite, requireConfigUnitInterval as requireFraction } from \"../core/record-validation.js\";\nimport { parseNonNegativeFact, parsePositiveFact } from \"../sensor/raw-readout.js\";\n\n/** The scope flags every stabilization profile declares false, in this order (shared with the generic tier assets). */\nexport const STABILIZATION_UNMODELED_SCOPE = /* @__PURE__ */ Object.freeze({ controlTransientModeled: false as const, spontaneousDriftModeled: false as const,\n cameraTranslationCorrectionModeled: false as const, digitalStabilizationIncluded: false as const, supportPolicyIncluded: false as const,\n stopRatingUsedAsDynamicResponse: false as const });\n\nexport const STABILIZATION_SYSTEM_PROFILE_SCHEMA_VERSION =\n \"0.1.0\" as const;\nexport const STABILIZATION_DISTURBANCE_TRAJECTORY_VERSION =\n \"0.1.0\" as const;\n\nexport type StabilizationRotationAxis =\n | \"pitch\"\n | \"yaw\"\n | \"roll\";\n\nexport type PhysicalStabilizationArchitecture =\n | \"off\"\n | \"sensor-shift\"\n | \"lens-optical\"\n | \"coordinated-physical\";\n\nexport type StabilizationCaptureKind =\n | \"still\"\n | \"video\";\n\nexport interface StabilizationAngularStateRad {\n pitch: number;\n yaw: number;\n roll: number;\n}\n\nexport interface StabilizationDisturbanceSample {\n timeSecondsFromCaptureReference:\n number;\n angularDisplacementRad:\n StabilizationAngularStateRad;\n}\n\nexport interface StabilizationDisturbanceTrajectory {\n version:\n typeof STABILIZATION_DISTURBANCE_TRAJECTORY_VERSION;\n trajectoryId: string;\n timeReference:\n \"first-opening-boundary-phase\";\n samples:\n readonly StabilizationDisturbanceSample[];\n initialAngularDisplacementIsZero:\n true;\n cameraTranslationIncluded:\n false;\n subjectMotionIncluded:\n false;\n supportStateEncoded:\n false;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface StabilizationAxisResponseProfile {\n axis: StabilizationRotationAxis;\n correctionGain:\n EvidenceBackedFact<number>;\n latencySeconds:\n EvidenceBackedFact<number>;\n maximumCorrectionAngleRad:\n EvidenceBackedFact<number>;\n}\n\nexport type StabilizationPanningPolicy =\n | {\n kind: \"none\";\n }\n | {\n kind:\n \"declared-axis-bypass\";\n axis:\n StabilizationRotationAxis;\n evidence:\n readonly EvidenceProvenance[];\n };\n\nexport interface StabilizationCoordinatedAllocation {\n bodyFraction: number;\n lensFraction: number;\n evidence: readonly EvidenceProvenance[];\n totalCorrectionAppliedOnce:\n true;\n}\n\nexport interface StabilizationSystemProfile {\n schemaVersion:\n typeof STABILIZATION_SYSTEM_PROFILE_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n profileKind:\n \"generic-synthetic\";\n scientificStatus:\n \"approximation\";\n architecture:\n PhysicalStabilizationArchitecture;\n captureKind:\n StabilizationCaptureKind;\n axisResponses:\n readonly StabilizationAxisResponseProfile[];\n panningPolicy:\n StabilizationPanningPolicy;\n coordinatedAllocation?:\n StabilizationCoordinatedAllocation;\n controlTransientModeled: false;\n spontaneousDriftModeled: false;\n cameraTranslationCorrectionModeled:\n false;\n digitalStabilizationIncluded:\n false;\n supportPolicyIncluded: false;\n stopRatingUsedAsDynamicResponse:\n false;\n evidence: readonly EvidenceProvenance[];\n limitations: readonly string[];\n}\n\nexport interface CalculateStabilizedRotationTrajectoryInput {\n disturbance:\n StabilizationDisturbanceTrajectory;\n profile:\n StabilizationSystemProfile;\n captureKind:\n StabilizationCaptureKind;\n}\n\nexport interface StabilizationAxisResolution {\n axis: StabilizationRotationAxis;\n disturbanceAngleRad: number;\n delayedMeasuredAngleRad: number;\n requestedCorrectionAngleRad:\n number;\n appliedCorrectionAngleRad:\n number;\n residualAngleRad: number;\n correctionGain: number;\n latencySeconds: number;\n maximumCorrectionAngleRad:\n number;\n bypassedForDeclaredPan:\n boolean;\n correctionLimitReached:\n boolean;\n}\n\nexport interface StabilizedRotationSample {\n timeSecondsFromCaptureReference:\n number;\n disturbanceAngularDisplacementRad:\n StabilizationAngularStateRad;\n appliedCorrectionAngularDisplacementRad:\n StabilizationAngularStateRad;\n residualAngularDisplacementRad:\n StabilizationAngularStateRad;\n axes:\n readonly StabilizationAxisResolution[];\n}\n\nexport interface StabilizedRotationTrajectory {\n profileId: string;\n profileVersion: string;\n trajectoryId: string;\n architecture:\n PhysicalStabilizationArchitecture;\n captureKind:\n StabilizationCaptureKind;\n timeReference:\n \"first-opening-boundary-phase\";\n samples:\n readonly StabilizedRotationSample[];\n correctionModel:\n \"delayed-linear-image-equivalent-angular-response\";\n supportStateConsumed: false;\n translationCorrectionModeled:\n false;\n digitalStabilizationApplied:\n false;\n digitalStabilizationOwnedBy:\n \"downstream-geometric-correction-composition\";\n coordinatedCorrectionDoubleCounted:\n false;\n zeroDisturbanceCanCreateMotion:\n false;\n}\n\nexport interface CalculateStabilizedCaptureTemporalSamplesInput {\n disturbance:\n StabilizationDisturbanceTrajectory;\n profile:\n StabilizationSystemProfile;\n captureKind:\n StabilizationCaptureKind;\n timing:\n ResolvedCaptureModeTiming;\n samplePointsNative:\n readonly RasterPoint[];\n temporalSampleCount: number;\n}\n\nexport interface StabilizedCaptureTemporalNode {\n temporalSampleIndex: number;\n localExposurePhase: number;\n captureTimeSecondsFromReference:\n number;\n normalizedTimeWeight: number;\n timeMeasureSeconds: number;\n stabilization:\n StabilizedRotationSample;\n}\n\nexport interface StabilizedCaptureTemporalPoint {\n destinationPointNative:\n RasterPoint;\n localExposureWindow: {\n startSecondsFromCaptureReference:\n number;\n endSecondsFromCaptureReference:\n number;\n durationSeconds: number;\n };\n nodes:\n readonly StabilizedCaptureTemporalNode[];\n}\n\nexport interface StabilizedCaptureTemporalSamples {\n profileId: string;\n trajectoryId: string;\n captureModeId: string;\n timingProfileId: string;\n captureKind:\n StabilizationCaptureKind;\n architecture:\n PhysicalStabilizationArchitecture;\n timeReference:\n \"first-opening-boundary-phase\";\n quadratureScheme:\n \"uniform-midpoint\";\n temporalSampleCount: number;\n points:\n readonly StabilizedCaptureTemporalPoint[];\n sensorReadoutTimingUsedAsExposureTiming:\n false;\n supportStateConsumed: false;\n translationCorrectionModeled:\n false;\n digitalStabilizationApplied:\n false;\n}\n\nconst AXES =\n new Set<StabilizationRotationAxis>([\n \"pitch\",\n \"yaw\",\n \"roll\"\n ]);\n\nconst ARCHITECTURES =\n new Set<PhysicalStabilizationArchitecture>([\n \"off\",\n \"sensor-shift\",\n \"lens-optical\",\n \"coordinated-physical\"\n ]);\n\nconst CAPTURE_KINDS =\n new Set<StabilizationCaptureKind>([\n \"still\",\n \"video\"\n ]);\n\nfunction parseFractionFact(\n value: unknown,\n path: string\n): EvidenceBackedFact<number> {\n const record =\n requireRecord(value, path, [\"value\", \"evidence\"]);\n return {\n value:\n requireFraction(\n record.value,\n path + \".value\"\n ),\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\nfunction parseAxis(\n value: unknown,\n path: string\n): StabilizationRotationAxis {\n if (\n typeof value !== \"string\" ||\n !AXES.has(\n value as\n StabilizationRotationAxis\n )\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value as\n StabilizationRotationAxis;\n}\n\nfunction parseAxisResponse(\n value: unknown,\n path: string\n): StabilizationAxisResponseProfile {\n const record =\n requireRecord(value, path, [\"axis\", \"correctionGain\", \"latencySeconds\", \"maximumCorrectionAngleRad\"]);\n return {\n axis:\n parseAxis(\n record.axis,\n path + \".axis\"\n ),\n correctionGain:\n parseFractionFact(\n record.correctionGain,\n path +\n \".correctionGain\"\n ),\n latencySeconds:\n parseNonNegativeFact(\n record.latencySeconds,\n path +\n \".latencySeconds\"\n ),\n maximumCorrectionAngleRad:\n parsePositiveFact(\n record\n .maximumCorrectionAngleRad,\n path +\n \".maximumCorrectionAngleRad\"\n )\n };\n}\n\nfunction parsePanningPolicy(\n value: unknown,\n path: string\n): StabilizationPanningPolicy {\n const record =\n requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", { none: [\"kind\"], \"declared-axis-bypass\": [\"kind\", \"axis\", \"evidence\"] }, path);\n if (record.kind === \"none\") {\n return {\n kind: \"none\"\n };\n }\n if (\n record.kind ===\n \"declared-axis-bypass\"\n ) {\n return {\n kind:\n \"declared-axis-bypass\",\n axis:\n parseAxis(\n record.axis,\n path + \".axis\"\n ),\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n }\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseCoordinatedAllocation(\n value: unknown,\n path: string\n): StabilizationCoordinatedAllocation {\n const record =\n requireRecord(value, path, [\"totalCorrectionAppliedOnce\", \"bodyFraction\", \"lensFraction\", \"evidence\"]);\n if (\n record\n .totalCorrectionAppliedOnce !==\n true\n ) {\n throw new InvalidConfigurationError(\n path +\n \".totalCorrectionAppliedOnce must be true.\"\n );\n }\n const bodyFraction =\n requireFraction(\n record.bodyFraction,\n path + \".bodyFraction\"\n );\n const lensFraction =\n requireFraction(\n record.lensFraction,\n path + \".lensFraction\"\n );\n if (\n Math.abs(\n bodyFraction +\n lensFraction -\n 1\n ) >\n 1e-12\n ) {\n throw new InvalidConfigurationError(\n path +\n \" bodyFraction + lensFraction must equal one.\"\n );\n }\n return {\n bodyFraction,\n lensFraction,\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n ),\n totalCorrectionAppliedOnce:\n true\n };\n}\n\n/**\n * Validates an untrusted declaration and returns the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected here.\n *\n * The generic stabilizer takes a declared angular disturbance (camera shake) and applies a per-axis\n * response, latency, travel limits and a panning policy. The leftover (residual) motion feeds the\n * existing temporal mapping. No commercial IBIS (in-body) or OIS (optical) calibration is supplied,\n * no arbitrary \"stops\" rating is used, and body/lens coordination is never inferred.\n * @param value - unknown. Untrusted input; TypeScript types alone are not validation.\n * @returns StabilizationSystemProfile. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function parseStabilizationSystemProfile(\n value: unknown\n): StabilizationSystemProfile {\n const record =\n requireRecord(\n value,\n \"stabilizationSystemProfile\", [\"schemaVersion\", \"profileKind\", \"scientificStatus\", \"architecture\", \"captureKind\", \"axisResponses\", \"panningPolicy\", \"coordinatedAllocation\", \"profileId\", \"profileVersion\", \"evidence\", \"limitations\", \"controlTransientModeled\", \"spontaneousDriftModeled\", \"cameraTranslationCorrectionModeled\", \"digitalStabilizationIncluded\", \"supportPolicyIncluded\", \"stopRatingUsedAsDynamicResponse\"]\n );\n if (\n record.schemaVersion !==\n STABILIZATION_SYSTEM_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'stabilizationSystemProfile.schemaVersion must be \"' +\n STABILIZATION_SYSTEM_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n if (\n record.profileKind !==\n \"generic-synthetic\" ||\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n 'stabilizationSystemProfile schema 0.1.0 requires profileKind \"generic-synthetic\" and scientificStatus \"approximation\".'\n );\n }\n if (\n typeof record.architecture !==\n \"string\" ||\n !ARCHITECTURES.has(\n record.architecture as\n PhysicalStabilizationArchitecture\n )\n ) {\n throw new InvalidConfigurationError(\n \"stabilizationSystemProfile.architecture is invalid.\"\n );\n }\n if (\n typeof record.captureKind !==\n \"string\" ||\n !CAPTURE_KINDS.has(\n record.captureKind as\n StabilizationCaptureKind\n )\n ) {\n throw new InvalidConfigurationError(\n \"stabilizationSystemProfile.captureKind is invalid.\"\n );\n }\n\n for (\n const key of [\n \"controlTransientModeled\",\n \"spontaneousDriftModeled\",\n \"cameraTranslationCorrectionModeled\",\n \"digitalStabilizationIncluded\",\n \"supportPolicyIncluded\",\n \"stopRatingUsedAsDynamicResponse\"\n ] as const\n ) {\n if (record[key] !== false) {\n throw new InvalidConfigurationError(\n \"stabilizationSystemProfile.\" +\n key +\n \" must be false in schema 0.1.0.\"\n );\n }\n }\n\n if (\n !Array.isArray(\n record.axisResponses\n )\n ) {\n throw new InvalidConfigurationError(\n \"stabilizationSystemProfile.axisResponses must be an array.\"\n );\n }\n const axisResponses =\n record.axisResponses.map(\n (entry, index) =>\n parseAxisResponse(\n entry,\n \"stabilizationSystemProfile.axisResponses[\" +\n index +\n \"]\"\n )\n );\n const axes =\n axisResponses.map(\n (entry) =>\n entry.axis\n );\n if (\n new Set(axes).size !==\n axes.length\n ) {\n throw new InvalidConfigurationError(\n \"stabilizationSystemProfile.axisResponses must not contain duplicate axes.\"\n );\n }\n\n const architecture =\n record.architecture as\n PhysicalStabilizationArchitecture;\n if (\n architecture === \"off\" &&\n axisResponses.length !== 0\n ) {\n throw new InvalidConfigurationError(\n \"An off stabilization profile must not declare axis responses.\"\n );\n }\n if (\n architecture !== \"off\" &&\n axisResponses.length === 0\n ) {\n throw new InvalidConfigurationError(\n \"An enabled physical stabilization profile must declare at least one axis response.\"\n );\n }\n\n const panningPolicy =\n parsePanningPolicy(\n record.panningPolicy,\n \"stabilizationSystemProfile.panningPolicy\"\n );\n if (\n architecture === \"off\" &&\n panningPolicy.kind !== \"none\"\n ) {\n throw new InvalidConfigurationError(\n \"An off stabilization profile must use panningPolicy.kind \\\"none\\\".\"\n );\n }\n if (\n panningPolicy.kind ===\n \"declared-axis-bypass\" &&\n !axisResponses.some(\n (entry) =>\n entry.axis ===\n panningPolicy.axis\n )\n ) {\n throw new InvalidConfigurationError(\n \"Declared panning bypass axis must exist in axisResponses.\"\n );\n }\n\n const coordinatedAllocation =\n record.coordinatedAllocation ===\n undefined\n ? undefined\n : parseCoordinatedAllocation(\n record.coordinatedAllocation,\n \"stabilizationSystemProfile.coordinatedAllocation\"\n );\n if (\n architecture ===\n \"coordinated-physical\" &&\n coordinatedAllocation ===\n undefined\n ) {\n throw new InvalidConfigurationError(\n \"Coordinated physical stabilization requires an explicit body/lens correction allocation.\"\n );\n }\n if (\n architecture !==\n \"coordinated-physical\" &&\n coordinatedAllocation !==\n undefined\n ) {\n throw new InvalidConfigurationError(\n \"Only coordinated physical stabilization may declare coordinatedAllocation.\"\n );\n }\n\n return {\n schemaVersion:\n STABILIZATION_SYSTEM_PROFILE_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"stabilizationSystemProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"stabilizationSystemProfile.profileVersion\"\n ),\n profileKind:\n \"generic-synthetic\",\n scientificStatus:\n \"approximation\",\n architecture,\n captureKind:\n record.captureKind as\n StabilizationCaptureKind,\n axisResponses,\n panningPolicy,\n ...(coordinatedAllocation ===\n undefined\n ? {}\n : {\n coordinatedAllocation\n }),\n ...STABILIZATION_UNMODELED_SCOPE,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"stabilizationSystemProfile.evidence\"\n ),\n limitations:\n parseLimitations(\n record.limitations,\n \"stabilizationSystemProfile.limitations\"\n )\n };\n}\n\nfunction parseAngularState(\n value: unknown,\n path: string\n): StabilizationAngularStateRad {\n const record =\n requireRecord(value, path, [\"pitch\", \"yaw\", \"roll\"]);\n return {\n pitch:\n requireFinite(\n record.pitch,\n path + \".pitch\"\n ),\n yaw:\n requireFinite(\n record.yaw,\n path + \".yaw\"\n ),\n roll:\n requireFinite(\n record.roll,\n path + \".roll\"\n )\n };\n}\n\n/**\n * Validates an untrusted declaration and returns the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected here.\n *\n * The generic stabilizer takes a declared angular disturbance (camera shake) and applies a per-axis\n * response, latency, travel limits and a panning policy. The leftover (residual) motion feeds the\n * existing temporal mapping. No commercial IBIS (in-body) or OIS (optical) calibration is supplied,\n * no arbitrary \"stops\" rating is used, and body/lens coordination is never inferred.\n * @param value - unknown. Untrusted input; TypeScript types alone are not validation.\n * @returns StabilizationDisturbanceTrajectory. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function parseStabilizationDisturbanceTrajectory(\n value: unknown\n): StabilizationDisturbanceTrajectory {\n const record =\n requireRecord(\n value,\n \"stabilizationDisturbanceTrajectory\", [\"version\", \"timeReference\", \"initialAngularDisplacementIsZero\", \"cameraTranslationIncluded\", \"subjectMotionIncluded\", \"supportStateEncoded\", \"samples\", \"trajectoryId\", \"evidence\", \"limitations\"]\n );\n if (\n record.version !==\n STABILIZATION_DISTURBANCE_TRAJECTORY_VERSION ||\n record.timeReference !==\n \"first-opening-boundary-phase\" ||\n record\n .initialAngularDisplacementIsZero !==\n true ||\n record\n .cameraTranslationIncluded !==\n false ||\n record.subjectMotionIncluded !==\n false ||\n record.supportStateEncoded !==\n false\n ) {\n throw new InvalidConfigurationError(\n \"stabilizationDisturbanceTrajectory metadata is invalid for version 0.1.0.\"\n );\n }\n if (\n !Array.isArray(record.samples) ||\n record.samples.length < 2\n ) {\n throw new InvalidConfigurationError(\n \"stabilizationDisturbanceTrajectory.samples must contain at least two samples.\"\n );\n }\n\n let previousTime =\n Number.NEGATIVE_INFINITY;\n const samples =\n record.samples.map(\n (entry, index) => {\n const path =\n \"stabilizationDisturbanceTrajectory.samples[\" +\n index +\n \"]\";\n const sample =\n requireRecord(\n entry,\n path, [\"timeSecondsFromCaptureReference\", \"angularDisplacementRad\"]\n );\n const time =\n requireNonNegativeFinite(\n sample\n .timeSecondsFromCaptureReference,\n path +\n \".timeSecondsFromCaptureReference\"\n );\n if (time <= previousTime) {\n throw new InvalidConfigurationError(\n \"stabilizationDisturbanceTrajectory sample times must be strictly increasing.\"\n );\n }\n previousTime = time;\n return {\n timeSecondsFromCaptureReference:\n time,\n angularDisplacementRad:\n parseAngularState(\n sample\n .angularDisplacementRad,\n path +\n \".angularDisplacementRad\"\n )\n };\n }\n );\n\n const first =\n samples[0]!;\n if (\n first\n .timeSecondsFromCaptureReference !==\n 0 ||\n first\n .angularDisplacementRad\n .pitch !== 0 ||\n first\n .angularDisplacementRad\n .yaw !== 0 ||\n first\n .angularDisplacementRad\n .roll !== 0\n ) {\n throw new InvalidConfigurationError(\n \"stabilizationDisturbanceTrajectory must begin at capture-reference t=0 with zero angular displacement.\"\n );\n }\n\n return {\n version:\n STABILIZATION_DISTURBANCE_TRAJECTORY_VERSION,\n trajectoryId:\n requireNonEmptyString(\n record.trajectoryId,\n \"stabilizationDisturbanceTrajectory.trajectoryId\"\n ),\n timeReference:\n \"first-opening-boundary-phase\",\n samples,\n initialAngularDisplacementIsZero:\n true,\n cameraTranslationIncluded:\n false,\n subjectMotionIncluded:\n false,\n supportStateEncoded:\n false,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"stabilizationDisturbanceTrajectory.evidence\"\n ),\n limitations:\n parseLimitations(\n record.limitations,\n \"stabilizationDisturbanceTrajectory.limitations\"\n )\n };\n}\n\n/**\n * Lookup index over a parsed disturbance trajectory, built for evaluation. Support times are copied\n * once into a Float64Array (exact IEEE-754 values). Each lookup is then an O(log n) binary search\n * instead of an O(n) scan. The interpolation arithmetic is unchanged.\n */\ninterface DisturbanceIndex {\n readonly samples:\n StabilizationDisturbanceTrajectory[\"samples\"];\n readonly times: Float64Array;\n}\n\nfunction indexDisturbance(\n trajectory:\n StabilizationDisturbanceTrajectory\n): DisturbanceIndex {\n const times =\n new Float64Array(\n trajectory.samples.length\n );\n for (\n let index = 0;\n index < times.length;\n index += 1\n ) {\n times[index] =\n trajectory.samples[index]!\n .timeSecondsFromCaptureReference;\n }\n return {\n samples:\n trajectory.samples,\n times\n };\n}\n\n/**\n * Returns the left index of the support segment used for `timeSeconds`. Returns -1 for the final support\n * time, which uses its stored value. The chosen segment is exactly the one a first-match linear scan\n * would pick: the smallest `i` with `t[i] <= timeSeconds <= t[i + 1]`. Support times strictly\n * increase, so a time that equals an interior support time uses the segment on its left.\n */\nfunction locateDisturbanceSegment(\n disturbance: DisturbanceIndex,\n timeSeconds: number\n): number {\n const times =\n disturbance.times;\n const lastIndex =\n times.length - 1;\n if (\n timeSeconds < times[0]! ||\n timeSeconds > times[lastIndex]!\n ) {\n throw new InvalidScientificInputError(\n \"Requested stabilization evaluation time lies outside the disturbance trajectory support.\"\n );\n }\n\n if (\n timeSeconds ===\n times[lastIndex]!\n ) {\n return -1;\n }\n\n // Lower bound: first index whose support time is >= timeSeconds.\n let low = 0;\n let high = lastIndex;\n while (low < high) {\n const middle =\n (low + high) >>> 1;\n if (\n times[middle]! >=\n timeSeconds\n ) {\n high = middle;\n } else {\n low = middle + 1;\n }\n }\n const index =\n low === 0 ? 0 : low - 1;\n if (\n !(\n timeSeconds >=\n times[index]! &&\n timeSeconds <=\n times[index + 1]!\n )\n ) {\n throw new InvalidScientificInputError(\n \"Disturbance trajectory interpolation failed.\"\n );\n }\n return index;\n}\n\nfunction interpolateDisturbanceSegment(\n disturbance: DisturbanceIndex,\n segmentIndex: number,\n timeSeconds: number,\n axis:\n StabilizationRotationAxis\n): number {\n const samples =\n disturbance.samples;\n if (segmentIndex < 0) {\n return samples[\n samples.length - 1\n ]!\n .angularDisplacementRad[\n axis\n ];\n }\n const left =\n samples[segmentIndex]!;\n const right =\n samples[\n segmentIndex + 1\n ]!;\n const duration =\n right\n .timeSecondsFromCaptureReference -\n left\n .timeSecondsFromCaptureReference;\n const phase =\n duration === 0\n ? 0\n : (\n timeSeconds -\n left\n .timeSecondsFromCaptureReference\n ) /\n duration;\n const a =\n left\n .angularDisplacementRad[\n axis\n ];\n const b =\n right\n .angularDisplacementRad[\n axis\n ];\n return (\n a +\n (b - a) * phase\n );\n}\n\nfunction interpolateAxis(\n disturbance: DisturbanceIndex,\n timeSeconds: number,\n axis:\n StabilizationRotationAxis\n): number {\n return interpolateDisturbanceSegment(\n disturbance,\n locateDisturbanceSegment(\n disturbance,\n timeSeconds\n ),\n timeSeconds,\n axis\n );\n}\n\nfunction axisValue(\n state:\n StabilizationAngularStateRad,\n axis:\n StabilizationRotationAxis\n): number {\n return state[axis];\n}\n\nfunction setAxisValue(\n state:\n StabilizationAngularStateRad,\n axis:\n StabilizationRotationAxis,\n value: number\n): void {\n state[axis] = value;\n}\n\nfunction clampSymmetric(\n value: number,\n limit: number\n): number {\n return Math.max(\n -limit,\n Math.min(limit, value)\n );\n}\n\ntype AxisResponseIndex = ReadonlyMap<\n StabilizationRotationAxis,\n StabilizationSystemProfile[\"axisResponses\"][number]\n>;\n\n/** Built once per calculation. Later entries win, as with a per-evaluation Map. */\nfunction indexAxisResponses(\n profile:\n StabilizationSystemProfile\n): AxisResponseIndex {\n return new Map(\n profile.axisResponses.map(\n (response) => [\n response.axis,\n response\n ] as const\n )\n );\n}\n\nfunction evaluateAtTime(\n disturbance: DisturbanceIndex,\n profile:\n StabilizationSystemProfile,\n responses: AxisResponseIndex,\n timeSeconds: number\n): StabilizedRotationSample {\n // One segment lookup serves all three axes at the same time.\n const segment =\n locateDisturbanceSegment(\n disturbance,\n timeSeconds\n );\n const current:\n StabilizationAngularStateRad = {\n pitch:\n interpolateDisturbanceSegment(\n disturbance,\n segment,\n timeSeconds,\n \"pitch\"\n ),\n yaw:\n interpolateDisturbanceSegment(\n disturbance,\n segment,\n timeSeconds,\n \"yaw\"\n ),\n roll:\n interpolateDisturbanceSegment(\n disturbance,\n segment,\n timeSeconds,\n \"roll\"\n )\n };\n const correction:\n StabilizationAngularStateRad = {\n pitch: 0,\n yaw: 0,\n roll: 0\n };\n const residual:\n StabilizationAngularStateRad = {\n ...current\n };\n\n const axes =\n [\"pitch\", \"yaw\", \"roll\"] as const;\n const resolvedAxes =\n axes.map((axis) => {\n const response =\n responses.get(axis);\n const bypassed =\n profile.panningPolicy.kind ===\n \"declared-axis-bypass\" &&\n profile.panningPolicy.axis ===\n axis;\n\n if (\n profile.architecture ===\n \"off\" ||\n response === undefined ||\n bypassed\n ) {\n return {\n axis,\n disturbanceAngleRad:\n axisValue(\n current,\n axis\n ),\n delayedMeasuredAngleRad:\n 0,\n requestedCorrectionAngleRad:\n 0,\n appliedCorrectionAngleRad:\n 0,\n residualAngleRad:\n axisValue(\n current,\n axis\n ),\n correctionGain:\n response?.correctionGain\n .value ?? 0,\n latencySeconds:\n response?.latencySeconds\n .value ?? 0,\n maximumCorrectionAngleRad:\n response\n ?.maximumCorrectionAngleRad\n .value ?? 0,\n bypassedForDeclaredPan:\n bypassed,\n correctionLimitReached:\n false\n };\n }\n\n const delayedTime =\n timeSeconds -\n response\n .latencySeconds.value;\n const delayedMeasured =\n delayedTime < 0\n ? 0\n : interpolateAxis(\n disturbance,\n delayedTime,\n axis\n );\n const requested =\n delayedMeasured *\n response\n .correctionGain.value;\n const applied =\n clampSymmetric(\n requested,\n response\n .maximumCorrectionAngleRad\n .value\n );\n const residualAngle =\n axisValue(\n current,\n axis\n ) -\n applied;\n\n setAxisValue(\n correction,\n axis,\n applied\n );\n setAxisValue(\n residual,\n axis,\n residualAngle\n );\n\n return {\n axis,\n disturbanceAngleRad:\n axisValue(\n current,\n axis\n ),\n delayedMeasuredAngleRad:\n delayedMeasured,\n requestedCorrectionAngleRad:\n requested,\n appliedCorrectionAngleRad:\n applied,\n residualAngleRad:\n residualAngle,\n correctionGain:\n response\n .correctionGain.value,\n latencySeconds:\n response\n .latencySeconds.value,\n maximumCorrectionAngleRad:\n response\n .maximumCorrectionAngleRad\n .value,\n bypassedForDeclaredPan:\n false,\n correctionLimitReached:\n applied !== requested\n };\n });\n\n return {\n timeSecondsFromCaptureReference:\n timeSeconds,\n disturbanceAngularDisplacementRad:\n current,\n appliedCorrectionAngularDisplacementRad:\n correction,\n residualAngularDisplacementRad:\n residual,\n axes:\n resolvedAxes\n };\n}\n\n/**\n * Runs the declared generic per-axis controller against an explicit angular disturbance trajectory.\n * Returns the residual motion, with diagnostics for latency and travel limits.\n *\n * The generic stabilizer takes a declared angular disturbance (camera shake) and applies a per-axis\n * response, latency, travel limits and a panning policy. The leftover (residual) motion feeds the\n * existing temporal mapping. No commercial IBIS (in-body) or OIS (optical) calibration is supplied,\n * no arbitrary \"stops\" rating is used, and body/lens coordination is never inferred.\n * @param input - CalculateStabilizedRotationTrajectoryInput. See that type for coordinates, units and profile binding.\n * @returns CalculationResult<StabilizedRotationTrajectory>. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function calculateStabilizedRotationTrajectory(\n input:\n CalculateStabilizedRotationTrajectoryInput\n): CalculationResult<StabilizedRotationTrajectory> {\n requireInputKeys(input, \"calculateStabilizedRotationTrajectory\", [\"disturbance\", \"profile\", \"captureKind\"]);\n const disturbance =\n parseStabilizationDisturbanceTrajectory(\n input.disturbance\n );\n const profile =\n parseStabilizationSystemProfile(\n input.profile\n );\n\n if (\n input.captureKind !==\n profile.captureKind\n ) {\n throw new InvalidScientificInputError(\n \"captureKind must exactly match the stabilization profile captureKind.\"\n );\n }\n\n const disturbanceIndex =\n indexDisturbance(disturbance);\n const responses =\n indexAxisResponses(profile);\n const samples =\n disturbance.samples.map(\n (sample) =>\n evaluateAtTime(\n disturbanceIndex,\n profile,\n responses,\n sample\n .timeSecondsFromCaptureReference\n )\n );\n\n return approximationResult(\n {\n profileId:\n profile.profileId,\n profileVersion:\n profile.profileVersion,\n trajectoryId:\n disturbance.trajectoryId,\n architecture:\n profile.architecture,\n captureKind:\n input.captureKind,\n timeReference:\n \"first-opening-boundary-phase\",\n samples,\n correctionModel:\n \"delayed-linear-image-equivalent-angular-response\",\n supportStateConsumed:\n false,\n translationCorrectionModeled:\n false,\n digitalStabilizationApplied:\n false,\n digitalStabilizationOwnedBy:\n \"downstream-geometric-correction-composition\",\n coordinatedCorrectionDoubleCounted:\n false,\n zeroDisturbanceCanCreateMotion:\n false\n },\n \"generic-time-domain-physical-stabilization\",\n \"1.0.0\",\n [\n \"The stabilization response is a generic synthetic image-equivalent rotational correction, not a manufacturer-specific IBIS/OIS calibration.\",\n \"Correction uses explicit per-axis gain, latency and symmetric angular correction limits.\",\n \"A coordinated profile allocates one total correction between body and lens for descriptive ownership only; the total correction is applied once.\",\n \"Support state is not an input and never silently toggles stabilization.\",\n \"Declared panning bypass suppresses correction only on the explicitly selected axis; pan intent is never inferred.\",\n \"Camera translation/parallax correction is not modeled because translational image motion depends on scene depth.\",\n \"Digital stabilization is a separate downstream geometric/crop/resampling domain.\",\n \"CIPA-style stop ratings are not used as a dynamic response function.\",\n \"The legacy stabilizationStopsEquivalent approximation remains unchanged.\"\n ]\n );\n}\n\ntype ExposureWindowSample =\n ResolvedCaptureModeTiming[\"exposureWindows\"][\"samples\"][number];\ntype ExposureWindowIndex = ReadonlyMap<\n unknown,\n ReadonlyMap<unknown, readonly ExposureWindowSample[]>\n>;\n\n/**\n * Groups the committed exposure-window samples by native point, once per calculation, and keeps their\n * order. Map keys compare with SameValueZero, so lookups are filtered again with the original `===`\n * test: NaN never matches, and +0 matches -0.\n */\nfunction indexExposureWindows(\n timing:\n ResolvedCaptureModeTiming\n): ExposureWindowIndex {\n requireInputObject(timing, \"timing\");\n requireInputObject(timing.exposureWindows, \"timing.exposureWindows\");\n if (!Array.isArray(timing.exposureWindows.samples)) throw new InvalidConfigurationError(\"timing.exposureWindows.samples must be an array.\");\n timing.exposureWindows.samples.forEach((sample, index) => {\n requireInputObject(sample, \"timing.exposureWindows.samples[\" + index + \"]\");\n requireInputObject(sample.pointNative, \"timing.exposureWindows.samples[\" + index + \"].pointNative\");\n });\n const byX =\n new Map<\n unknown,\n Map<unknown, ExposureWindowSample[]>\n >();\n for (const sample of timing.exposureWindows.samples) {\n let byY =\n byX.get(sample.pointNative.x);\n if (byY === undefined) {\n byY = new Map();\n byX.set(\n sample.pointNative.x,\n byY\n );\n }\n const bucket =\n byY.get(sample.pointNative.y);\n if (bucket === undefined) {\n byY.set(\n sample.pointNative.y,\n [sample]\n );\n } else {\n bucket.push(sample);\n }\n }\n return byX;\n}\n\nfunction localExposureForPoint(\n windows: ExposureWindowIndex,\n point:\n RasterPoint\n): {\n start: number;\n end: number;\n duration: number;\n} {\n const matches =\n (\n windows\n .get(point.x)\n ?.get(point.y) ?? []\n ).filter(\n (sample) =>\n sample.pointNative.x ===\n point.x &&\n sample.pointNative.y ===\n point.y\n );\n if (matches.length !== 1) {\n throw new InvalidScientificInputError(\n \"Each stabilization sample point must match exactly one committed exposure-window sample point.\"\n );\n }\n const match =\n matches[0]!;\n return {\n start:\n match\n .startOffsetSecondsFromOpeningReference,\n end:\n match\n .endOffsetSecondsFromOpeningReference,\n duration:\n match\n .localExposureDurationSeconds\n };\n}\n\n/**\n * Feeds the residual stabilized rotation into the existing local-exposure temporal mapping. Shutter\n * timing is not changed, and no blur radius is invented.\n *\n * The generic stabilizer takes a declared angular disturbance (camera shake) and applies a per-axis\n * response, latency, travel limits and a panning policy. The leftover (residual) motion feeds the\n * existing temporal mapping. No commercial IBIS (in-body) or OIS (optical) calibration is supplied,\n * no arbitrary \"stops\" rating is used, and body/lens coordination is never inferred.\n * @param input - CalculateStabilizedCaptureTemporalSamplesInput. See that type for coordinates, units and profile binding.\n * @returns CalculationResult<StabilizedCaptureTemporalSamples>. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function calculateStabilizedCaptureTemporalSamples(\n input:\n CalculateStabilizedCaptureTemporalSamplesInput\n): CalculationResult<StabilizedCaptureTemporalSamples> {\n requireInputKeys(input, \"calculateStabilizedCaptureTemporalSamples\", [\"disturbance\", \"profile\", \"captureKind\", \"timing\", \"samplePointsNative\", \"temporalSampleCount\"]);\n requireInputObject(input.timing, \"timing\");\n const disturbance =\n parseStabilizationDisturbanceTrajectory(\n input.disturbance\n );\n const profile =\n parseStabilizationSystemProfile(\n input.profile\n );\n if (\n input.captureKind !==\n profile.captureKind\n ) {\n throw new InvalidScientificInputError(\n \"captureKind must exactly match the stabilization profile captureKind.\"\n );\n }\n requirePositiveInteger(\n \"temporalSampleCount\",\n input.temporalSampleCount\n );\n if (\n !Array.isArray(\n input.samplePointsNative\n ) ||\n input.samplePointsNative.length ===\n 0\n ) {\n throw new InvalidConfigurationError(\n \"samplePointsNative must be a non-empty array.\"\n );\n }\n input.samplePointsNative.forEach((point, index) => requireInputObject(point, \"samplePointsNative[\" + index + \"]\"));\n\n const totalNodeCount =\n input.temporalSampleCount *\n input.samplePointsNative.length;\n if (\n !Number.isSafeInteger(\n totalNodeCount\n )\n ) {\n throw new InvalidScientificInputError(\n \"temporalSampleCount × samplePointsNative.length must remain a safe integer.\"\n );\n }\n\n const disturbanceIndex =\n indexDisturbance(disturbance);\n const responses =\n indexAxisResponses(profile);\n let exposureWindowIndex:\n ExposureWindowIndex | undefined;\n const points =\n input.samplePointsNative.map(\n (point) => {\n exposureWindowIndex ??=\n indexExposureWindows(\n input.timing\n );\n const exposure =\n localExposureForPoint(\n exposureWindowIndex,\n point\n );\n const normalizedTimeWeight =\n 1 /\n input.temporalSampleCount;\n const timeMeasureSeconds =\n exposure.duration /\n input.temporalSampleCount;\n\n const nodes =\n Array.from(\n {\n length:\n input.temporalSampleCount\n },\n (\n _,\n temporalSampleIndex\n ) => {\n const localExposurePhase =\n (\n temporalSampleIndex +\n 0.5\n ) /\n input.temporalSampleCount;\n const captureTime =\n exposure.start +\n localExposurePhase *\n exposure.duration;\n return {\n temporalSampleIndex,\n localExposurePhase,\n captureTimeSecondsFromReference:\n captureTime,\n normalizedTimeWeight,\n timeMeasureSeconds,\n stabilization:\n evaluateAtTime(\n disturbanceIndex,\n profile,\n responses,\n captureTime\n )\n };\n }\n );\n\n return {\n destinationPointNative: {\n ...point\n },\n localExposureWindow: {\n startSecondsFromCaptureReference:\n exposure.start,\n endSecondsFromCaptureReference:\n exposure.end,\n durationSeconds:\n exposure.duration\n },\n nodes\n };\n }\n );\n\n return approximationResult(\n {\n profileId:\n profile.profileId,\n trajectoryId:\n disturbance.trajectoryId,\n captureModeId:\n input.timing.captureModeId,\n timingProfileId:\n input.timing.timingProfileId,\n captureKind:\n input.captureKind,\n architecture:\n profile.architecture,\n timeReference:\n \"first-opening-boundary-phase\",\n quadratureScheme:\n \"uniform-midpoint\",\n temporalSampleCount:\n input.temporalSampleCount,\n points,\n sensorReadoutTimingUsedAsExposureTiming:\n false,\n supportStateConsumed:\n false,\n translationCorrectionModeled:\n false,\n digitalStabilizationApplied:\n false\n },\n \"capture-local-stabilization-temporal-sampling\",\n \"1.0.0\",\n [\n \"Stabilization is evaluated at deterministic midpoint nodes inside each authoritative local exposure window of the exposure-window model.\",\n \"Sensor data-readout timing is not substituted for exposure timing.\",\n \"The result is rotational disturbance/correction/residual state only; it does not itself calculate image-plane mapping, radiance, blur, PSF or output pixels.\",\n \"Translation/parallax, subject motion, shutter shock, support vibration sources and digital stabilization remain separate domains.\"\n ]\n );\n}\n"]}
@@ -33,15 +33,20 @@ one-call capture, see the [Quick Start](QUICK_START.md). For every export, see t
33
33
  | Crop factor and 35 mm-equivalent focal length | [`calculateEquivalentFocalLength35Mm`](api/camera-equivalent-focal-length.md#calculateequivalentfocallength35mm) | Diagonal-based, against a 36 × 24 mm frame. |
34
34
  | Equivalent f-number, sensor area ratio and angles of view of a lens on a sensor | [`calculateSensorEquivalence`](api/camera-sensor-equivalence.md#calculatesensorequivalence) | Call once per sensor. `equivalentFNumber` is for depth of field, blur and total light (an approximation); `exposureFNumber` is the f-number on the lens. `basis` says exact or approximated for every value. |
35
35
  | Blur circle as a share of the frame or on a print | [`calculateBlurShareOfFrame`](api/camera-sensor-equivalence.md#calculateblurshareofframe) | Equal shares of the diagonal look the same at the same output size. |
36
+ | Largest print that looks sharp and clean, counting blur and noise | [`calculatePrintSizeLimitWithBlurAndNoise`](api/output-print-size-blur-noise.md#calculateprintsizelimitwithblurandnoise) | An approximation; names the limit (pixels, blur or noise); the criterion is the caller's. |
36
37
  | Pixels left after a centred crop | [`calculateCenteredCrop`](api/output-crop.md#calculatecenteredcrop) | Keeps the aspect ratio to whole pixels. |
38
+ | Crop to match a longer focal length | [`calculateCropToMatchFocalLength`](api/output-crop-to-match-focal-length.md#calculatecroptomatchfocallength) | Factor `target ÷ focal length` (exact at infinity focus) and the pixels left. 24 MP at 50 mm matched to 100 mm → factor 2, 3000 × 2000, 6 MP. |
39
+ | Aperture (entrance-pupil) diameter in mm | [`calculateApertureDiameter`](api/optics-aperture-diameter.md#calculateaperturediameter) | Focal length ÷ f-number, exact by definition at infinity focus. 50 mm f/2 → 25 mm. |
37
40
  | Motion blur for a shutter speed | [`calculateProjectedMotionBlur`](api/motion-projected-motion.md#calculateprojectedmotionblur) | Subject position and velocity in metres; blur in mm, and in pixels if you give a pixel pitch. |
38
41
  | Shutter time with an ND filter | [`calculateFilteredExposureTime`](api/exposure-filtered-exposure-time.md#calculatefilteredexposuretime) | Pass `GENERIC_ND_FILTER_PROFILES[3 | 6 | 10]` (idealized, exactly 2^-N) or your own front-of-lens filter profile(s), and optionally a shutter dial (for example `GENERIC_THIRD_STOP_SHUTTER_SECONDS`) for the nearest dial value. 1/125 s with a 10-stop filter → ≈ 8.19 s (8 s on the dial). |
42
+ | Which limits detail: the lens or the sensor | [`calculateDetailLimit`](api/optics-detail-limit.md#calculatedetaillimit) | Pass the sensor (`widthMm`, `heightMm`, `pixelWidth`), `lens: { kind: "ideal", focalLengthMm }` or `{ kind: "catalogue", lensId }`, the f-number and optionally `focus` and `fieldPosition`. `limitedBy` is `"lens"` or `"sensor"`; `limitingFactor` is `"diffraction"`, `"aberrations"`, `"defocus"` or `"pixel-pitch"`. The decision rule is an approximation. |
39
43
  | Video shutter angle to exposure time | [`calculateShutterAngleExposureSeconds`](api/motion-video-sequence.md#calculateshutterangleexposureseconds) | Positional arguments: frame rate (Hz), angle (degrees). |
40
44
  | Diffraction spot size | [`calculateAiryDisk`](api/optics-diffraction.md#calculateairydisk) | Ideal circular aperture; you choose the wavelength. |
41
45
  | Photons to electrons | [`calculatePhotoelectrons`](api/sensor-signal-noise.md#calculatephotoelectrons) | Mean value; you supply the quantum efficiency. |
42
46
  | Sensor noise and signal-to-noise ratio (SNR) | [`calculateSignalToNoise`](api/sensor-signal-noise.md#calculatesignaltonoise) | Shot noise plus read noise, in electrons. |
43
47
  | Colour temperature to a white point | [`calculateChromaticityFromCorrelatedColorTemperature`](api/color-illuminants.md#calculatechromaticityfromcorrelatedcolortemperature) | Kelvin and Duv (tint) to CIE 1931 xy. |
44
48
  | White point to colour temperature | [`calculateCorrelatedColorTemperature`](api/color-illuminants.md#calculatecorrelatedcolortemperature) | CIE 1931 xy to kelvin and Duv. |
49
+ | Fluorescent or LED light with realistic color rendering | [`createRepresentativeLightSourceIlluminant`](api/facade-representative-light-sources.md#createrepresentativelightsourceilluminant) | Photivra's own representative spectra (not named products), passed as `illuminant`; same-CCT LEDs render colors differently. Use `sensor.spectralStepNanometers: 5`. |
45
50
  | White balance from Kelvin and tint | [`createColorTemperatureWhiteBalanceIntent`](api/color-white-balance.md#createcolortemperaturewhitebalanceintent), then [`resolveColorTemperatureWhiteBalance`](api/color-white-balance.md#resolvecolortemperaturewhitebalance) | Needs an explicit camera colour matrix. In `simulateCapture()`, use `output.whiteBalance: { kelvin, tint }` instead. |
46
51
 
47
52
  If a task is not in this table, search the [API reference](API_REFERENCE.md) or the