@photivra/engine 2.18.0 → 2.19.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.
- package/CHANGELOG.md +68 -1
- package/CITATION.cff +1 -1
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/dist/capture/focus-control.js +2 -75
- package/dist/capture/focus-control.js.map +1 -1
- package/dist/capture/native-environment-lean.d.ts +1 -0
- package/dist/capture/native-environment-lean.js +1 -1
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-environment-optical-stage.d.ts +1 -0
- package/dist/capture/native-environment-optical-stage.js +2 -5
- package/dist/capture/native-environment-optical-stage.js.map +1 -1
- package/dist/capture/native-environment-raw.js +1 -5
- package/dist/capture/native-environment-raw.js.map +1 -1
- package/dist/capture/release-sequence.js +2 -47
- package/dist/capture/release-sequence.js.map +1 -1
- package/dist/color/white-balance.d.ts +2 -0
- package/dist/color/white-balance.js +3 -56
- package/dist/color/white-balance.js.map +1 -1
- package/dist/composition/image-formation-plan.d.ts +1 -0
- package/dist/composition/image-formation-plan.js +3 -49
- package/dist/composition/image-formation-plan.js.map +1 -1
- package/dist/core/evidence-provenance.js +1 -16
- package/dist/core/evidence-provenance.js.map +1 -1
- package/dist/core/record-validation.d.ts +54 -0
- package/dist/core/record-validation.js +176 -0
- package/dist/core/record-validation.js.map +1 -1
- package/dist/core/scientific-assurance.js +1 -18
- package/dist/core/scientific-assurance.js.map +1 -1
- package/dist/core/shared-helpers.d.ts +33 -0
- package/dist/core/shared-helpers.js +34 -0
- package/dist/core/shared-helpers.js.map +1 -0
- package/dist/core/spectral-composition.js +1 -36
- package/dist/core/spectral-composition.js.map +1 -1
- package/dist/core/spectral.js +1 -19
- package/dist/core/spectral.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/equipment/exposure-capabilities.d.ts +1 -0
- package/dist/equipment/exposure-capabilities.js +2 -36
- package/dist/equipment/exposure-capabilities.js.map +1 -1
- package/dist/equipment/iso-capabilities.js +2 -49
- package/dist/equipment/iso-capabilities.js.map +1 -1
- package/dist/equipment/metering-capabilities.js +1 -26
- package/dist/equipment/metering-capabilities.js.map +1 -1
- package/dist/equipment/release-capabilities.js +1 -53
- package/dist/equipment/release-capabilities.js.map +1 -1
- package/dist/exposure/auto-iso-slowest-shutter.js +1 -7
- package/dist/exposure/auto-iso-slowest-shutter.js.map +1 -1
- package/dist/exposure/exposure-duration-control.js +1 -16
- package/dist/exposure/exposure-duration-control.js.map +1 -1
- package/dist/exposure/exposure-mode-resolver.js +1 -17
- package/dist/exposure/exposure-mode-resolver.js.map +1 -1
- package/dist/exposure/filtered-exposure-time.d.ts +93 -0
- package/dist/exposure/filtered-exposure-time.js +129 -0
- package/dist/exposure/filtered-exposure-time.js.map +1 -0
- package/dist/exposure/flash-ttl.d.ts +1 -0
- package/dist/exposure/flash-ttl.js +1 -1
- package/dist/exposure/flash-ttl.js.map +1 -1
- package/dist/exposure/flash.js +1 -49
- package/dist/exposure/flash.js.map +1 -1
- package/dist/exposure/metering-scene-radiance.js +1 -25
- package/dist/exposure/metering-scene-radiance.js.map +1 -1
- package/dist/exposure/metering-target.js +1 -30
- package/dist/exposure/metering-target.js.map +1 -1
- package/dist/exposure/metering-temporal.js +1 -8
- package/dist/exposure/metering-temporal.js.map +1 -1
- package/dist/exposure/metering.js +1 -72
- package/dist/exposure/metering.js.map +1 -1
- package/dist/exposure/program-line.js +1 -45
- package/dist/exposure/program-line.js.map +1 -1
- package/dist/facade/develop-joined-parts.d.ts +29 -0
- package/dist/facade/develop-joined-parts.js +33 -0
- package/dist/facade/develop-joined-parts.js.map +1 -0
- package/dist/facade/generic-lens-capture.d.ts +4 -2
- package/dist/facade/generic-lens-capture.js +4 -2
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +37 -5
- package/dist/facade/simulate-capture.js +153 -96
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.js +1 -3
- package/dist/gpu/chart-composite-gpu.js.map +1 -1
- package/dist/gpu/chart-radiance-gpu.js +1 -5
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/gpu/display-view-quality-gpu.d.ts +13 -1
- package/dist/gpu/display-view-quality-gpu.js +4 -8
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.js +3 -25
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/gpu/sensor-stage-gpu.js +1 -5
- package/dist/gpu/sensor-stage-gpu.js.map +1 -1
- package/dist/gpu/webgpu-runtime.d.ts +2 -0
- package/dist/gpu/webgpu-runtime.js +3 -0
- package/dist/gpu/webgpu-runtime.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/motion/camera-rotation.js +1 -6
- package/dist/motion/camera-rotation.js.map +1 -1
- package/dist/motion/capture-rotation-inverse-mapping.d.ts +12 -0
- package/dist/motion/capture-rotation-inverse-mapping.js +2 -2
- package/dist/motion/capture-rotation-inverse-mapping.js.map +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.d.ts +1 -0
- package/dist/motion/capture-rotation-temporal-quadrature.js +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.js.map +1 -1
- package/dist/motion/capture-rotation-trajectory.js +2 -17
- package/dist/motion/capture-rotation-trajectory.js.map +1 -1
- package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts +1 -0
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js +3 -14
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js.map +1 -1
- package/dist/motion/extended-object-projection.js +5 -40
- package/dist/motion/extended-object-projection.js.map +1 -1
- package/dist/optics/atmospheric-haze.js +1 -7
- package/dist/optics/atmospheric-haze.js.map +1 -1
- package/dist/optics/brown-conrady-distortion.js +1 -7
- package/dist/optics/brown-conrady-distortion.js.map +1 -1
- package/dist/optics/complex-pupil-psf.d.ts +1 -0
- package/dist/optics/complex-pupil-psf.js +2 -84
- package/dist/optics/complex-pupil-psf.js.map +1 -1
- package/dist/optics/focus-state.js +1 -11
- package/dist/optics/focus-state.js.map +1 -1
- package/dist/optics/front-of-lens-filter.d.ts +5 -0
- package/dist/optics/front-of-lens-filter.js +3 -65
- package/dist/optics/front-of-lens-filter.js.map +1 -1
- package/dist/optics/generic-nd-filter-presets.d.ts +12 -0
- package/dist/optics/generic-nd-filter-presets.js +48 -0
- package/dist/optics/generic-nd-filter-presets.js.map +1 -0
- package/dist/optics/illumination-vignetting.js +1 -6
- package/dist/optics/illumination-vignetting.js.map +1 -1
- package/dist/optics/lens-psf-profile.d.ts +4 -1
- package/dist/optics/lens-psf-profile.js +12 -111
- package/dist/optics/lens-psf-profile.js.map +1 -1
- package/dist/optics/longitudinal-chromatic-aberration.js +1 -7
- package/dist/optics/longitudinal-chromatic-aberration.js.map +1 -1
- package/dist/optics/pupil-vignetting.js +1 -7
- package/dist/optics/pupil-vignetting.js.map +1 -1
- package/dist/optics/radial-distortion.js +1 -6
- package/dist/optics/radial-distortion.js.map +1 -1
- package/dist/optics/scene-to-sensor-irradiance.js +4 -96
- package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
- package/dist/optics/stray-light.d.ts +1 -0
- package/dist/optics/stray-light.js +1 -1
- package/dist/optics/stray-light.js.map +1 -1
- package/dist/optics/zernike-wavefront.js +1 -7
- package/dist/optics/zernike-wavefront.js.map +1 -1
- package/dist/output/capture-geometry.js +1 -8
- package/dist/output/capture-geometry.js.map +1 -1
- package/dist/output/developed-lens-corrections.d.ts +62 -0
- package/dist/output/developed-lens-corrections.js +135 -0
- package/dist/output/developed-lens-corrections.js.map +1 -0
- package/dist/output/generic-lens-corrections.d.ts +2 -6
- package/dist/output/generic-lens-corrections.js +3 -6
- package/dist/output/generic-lens-corrections.js.map +1 -1
- package/dist/output/geometric-transforms.js +1 -4
- package/dist/output/geometric-transforms.js.map +1 -1
- package/dist/output/native-capture-sdr.d.ts +2 -2
- package/dist/output/native-capture-sdr.js +3 -2
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/processing/development-detail.d.ts +29 -0
- package/dist/processing/development-detail.js +128 -107
- package/dist/processing/development-detail.js.map +1 -1
- package/dist/schema/illumination-temporal.js +3 -72
- package/dist/schema/illumination-temporal.js.map +1 -1
- package/dist/schema/illumination.d.ts +1 -0
- package/dist/schema/illumination.js +2 -65
- package/dist/schema/illumination.js.map +1 -1
- package/dist/schema/scene-radiance-temporal.js +2 -14
- package/dist/schema/scene-radiance-temporal.js.map +1 -1
- package/dist/schema/scene-radiance.js +2 -60
- package/dist/schema/scene-radiance.js.map +1 -1
- package/dist/schema/validation.d.ts +2 -0
- package/dist/schema/validation.js +2 -17
- package/dist/schema/validation.js.map +1 -1
- package/dist/sensor/accumulated-charge.js +2 -59
- package/dist/sensor/accumulated-charge.js.map +1 -1
- package/dist/sensor/architecture.js +1 -16
- package/dist/sensor/architecture.js.map +1 -1
- package/dist/sensor/camera-saturation-capacity.d.ts +1 -0
- package/dist/sensor/camera-saturation-capacity.js +3 -55
- package/dist/sensor/camera-saturation-capacity.js.map +1 -1
- package/dist/sensor/capture-color-sampling-binding.js +1 -26
- package/dist/sensor/capture-color-sampling-binding.js.map +1 -1
- package/dist/sensor/capture-mode-timing.js +1 -39
- package/dist/sensor/capture-mode-timing.js.map +1 -1
- package/dist/sensor/capture-mode.js +1 -23
- package/dist/sensor/capture-mode.js.map +1 -1
- package/dist/sensor/color-sampling.js +1 -26
- package/dist/sensor/color-sampling.js.map +1 -1
- package/dist/sensor/constant-rate-temporal-integration.js +2 -46
- package/dist/sensor/constant-rate-temporal-integration.js.map +1 -1
- package/dist/sensor/dark-current.js +2 -45
- package/dist/sensor/dark-current.js.map +1 -1
- package/dist/sensor/eqe-electron-rate.js +2 -35
- package/dist/sensor/eqe-electron-rate.js.map +1 -1
- package/dist/sensor/exposure-window.d.ts +5 -0
- package/dist/sensor/exposure-window.js +7 -22
- package/dist/sensor/exposure-window.js.map +1 -1
- package/dist/sensor/iso-gain.js +1 -7
- package/dist/sensor/iso-gain.js.map +1 -1
- package/dist/sensor/iso-signal-chain.js +1 -43
- package/dist/sensor/iso-signal-chain.js.map +1 -1
- package/dist/sensor/optical-stack.js +1 -25
- package/dist/sensor/optical-stack.js.map +1 -1
- package/dist/sensor/photon-energy.js +1 -26
- package/dist/sensor/photon-energy.js.map +1 -1
- package/dist/sensor/physical-charge-capacity.js +3 -77
- package/dist/sensor/physical-charge-capacity.js.map +1 -1
- package/dist/sensor/radiometry-readiness.js +2 -23
- package/dist/sensor/radiometry-readiness.js.map +1 -1
- package/dist/sensor/raw-readout.d.ts +3 -0
- package/dist/sensor/raw-readout.js +4 -66
- package/dist/sensor/raw-readout.js.map +1 -1
- package/dist/sensor/raw-reconstruction.js +2 -64
- package/dist/sensor/raw-reconstruction.js.map +1 -1
- package/dist/sensor/readout-exposure-linkage.js +1 -9
- package/dist/sensor/readout-exposure-linkage.js.map +1 -1
- package/dist/sensor/readout-timing.js +3 -57
- package/dist/sensor/readout-timing.js.map +1 -1
- package/dist/sensor/response-application-compatibility.d.ts +2 -0
- package/dist/sensor/response-application-compatibility.js +3 -29
- package/dist/sensor/response-application-compatibility.js.map +1 -1
- package/dist/sensor/response-operating-range.d.ts +1 -0
- package/dist/sensor/response-operating-range.js +3 -79
- package/dist/sensor/response-operating-range.js.map +1 -1
- package/dist/sensor/responsivity-photocurrent.js +4 -108
- package/dist/sensor/responsivity-photocurrent.js.map +1 -1
- package/dist/sensor/sampling-aperture.js +1 -25
- package/dist/sensor/sampling-aperture.js.map +1 -1
- package/dist/sensor/spatial-sample-reduction.js +2 -19
- package/dist/sensor/spatial-sample-reduction.js.map +1 -1
- package/dist/sensor/spatial-sampling-quadrature.js +1 -3
- package/dist/sensor/spatial-sampling-quadrature.js.map +1 -1
- package/dist/sensor/spatio-spectral-reduction.js +1 -18
- package/dist/sensor/spatio-spectral-reduction.js.map +1 -1
- package/dist/sensor/spectral-coverage.d.ts +10 -1
- package/dist/sensor/spectral-coverage.js +1 -1
- package/dist/sensor/spectral-coverage.js.map +1 -1
- package/dist/sensor/spectral-quadrature.js +2 -35
- package/dist/sensor/spectral-quadrature.js.map +1 -1
- package/dist/sensor/spectral-response.js +1 -47
- package/dist/sensor/spectral-response.js.map +1 -1
- package/dist/stabilization/camera-shake.js +1 -6
- package/dist/stabilization/camera-shake.js.map +1 -1
- package/dist/stabilization/system.js +2 -80
- package/dist/stabilization/system.js.map +1 -1
- package/docs/AGENT_GUIDE.md +1 -0
- package/docs/API_REFERENCE.md +41 -2
- package/docs/QUICK_START.md +90 -8
- package/docs/USAGE.md +47 -2
- package/docs/api/core-version.md +1 -1
- package/docs/api/exports.json +53 -3
- package/docs/api/exposure-filtered-exposure-time.md +105 -0
- package/docs/api/facade-develop-joined-parts.md +32 -0
- package/docs/api/facade-simulate-capture.md +36 -5
- package/docs/api/optics-generic-nd-filter-presets.md +34 -0
- package/docs/api/optics-lens-psf-profile.md +3 -1
- package/docs/api/output-developed-lens-corrections.md +12 -0
- package/docs/api/output-generic-lens-corrections.md +0 -9
- package/llms.txt +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iso-capabilities.js","sourceRoot":"","sources":["../../src/equipment/iso-capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * ISO capabilities: which standard, expanded and Auto ISO settings a body offers, and in which\n * capture modes.\n *\n * The parser validates untrusted input and returns the normalized typed contract. Unknown enum\n * values, missing required fields and incompatible scientific data are rejected.\n *\n * ISO is an exposure-index (EI) control setting. It does not create photons and says nothing about\n * read noise. Standard and expanded settings, limits per capture mode, and whether Auto ISO is\n * available are all stated explicitly. If availability is unknown, automatic control is not allowed.\n * @see docs/GENERIC_TIER_PRESETS.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport type {\n ResolvedGenericEquipmentExposureCapabilities,\n ResolvedNumericSettingGrid\n} from \"./exposure-capabilities.js\";\nimport { requireInputKeys, rejectUnknownFields, rejectUnknownVariantFields } from \"../core/record-validation.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport const ISO_CAPABILITY_PROFILE_SCHEMA_VERSION =\n \"0.1.0\" as const;\n\nexport type IsoCapabilityAvailability =\n | \"supported\"\n | \"unsupported\"\n | \"unknown\";\n\nexport interface IsoExposureIndexRange {\n minimum: number;\n maximum: number;\n}\n\nexport type IsoStandardSettingGrid =\n | {\n kind: \"continuous-within-range\";\n }\n | {\n kind: \"discrete-values\";\n values: readonly number[];\n };\n\nexport interface IsoExpandedSetting {\n settingId: string;\n label: string;\n direction: \"low\" | \"high\";\n exposureIndexEquivalent: number;\n autoIsoEligible: boolean;\n evidence: readonly EvidenceProvenance[];\n}\n\nexport type IsoAutoIsoCapability =\n | {\n availability: \"supported\";\n standardExposureIndexRange:\n IsoExposureIndexRange;\n evidence: readonly EvidenceProvenance[];\n }\n | {\n availability:\n | \"unsupported\"\n | \"unknown\";\n evidence: readonly EvidenceProvenance[];\n };\n\nexport interface IsoCaptureModePolicy {\n captureModeId: string;\n standardExposureIndexRange:\n IsoExposureIndexRange;\n expandedSettingIds:\n readonly string[];\n autoIso:\n IsoAutoIsoCapability;\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface IsoCapabilityProfile {\n schemaVersion:\n typeof ISO_CAPABILITY_PROFILE_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n capabilityMeaning:\n \"reported-exposure-index-capability-not-physical-gain\";\n standard: {\n exposureIndexRange:\n IsoExposureIndexRange;\n settingGrid:\n IsoStandardSettingGrid;\n };\n expandedSettings:\n readonly IsoExpandedSetting[];\n autoIso:\n IsoAutoIsoCapability;\n captureModePolicies:\n readonly IsoCaptureModePolicy[];\n evidence:\n readonly EvidenceProvenance[];\n}\n\nexport type RequestedIsoSetting =\n | {\n kind: \"standard\";\n exposureIndex: number;\n }\n | {\n kind: \"expanded\";\n settingId: string;\n };\n\nexport interface ResolveIsoCapabilityInput {\n profile:\n IsoCapabilityProfile;\n setting:\n RequestedIsoSetting;\n captureModeId?: string;\n}\n\nexport interface ResolvedIsoCapability {\n profileId: string;\n profileVersion: string;\n captureModeId: string | null;\n setting:\n | {\n kind: \"standard\";\n exposureIndex: number;\n }\n | {\n kind: \"expanded\";\n settingId: string;\n label: string;\n direction:\n \"low\" | \"high\";\n exposureIndexEquivalent:\n number;\n };\n reportedExposureIndex: number;\n expandedSetting: boolean;\n autoIsoEligible:\n boolean;\n standardExposureIndexRange:\n IsoExposureIndexRange;\n standardSettingGrid:\n IsoStandardSettingGrid;\n autoIso:\n IsoAutoIsoCapability;\n capturedPhotonExpectationModified:\n false;\n photonShotNoiseStatisticsModified:\n false;\n physicalGainInferred:\n false;\n conversionGainInferred:\n false;\n readNoiseInferred: false;\n saturationInferred: false;\n exactCommercialCameraBehaviorClaimed:\n false;\n}\n\nfunction requireRecord(\n value: unknown,\n path: string,\n allowedKeys: readonly string[] | null\n): UnknownRecord {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be an object.\"\n );\n }\n if (allowedKeys !== null) rejectUnknownFields(value, allowedKeys, path);\n return value as UnknownRecord;\n}\n\nfunction requireNonEmptyString(\n value: unknown,\n path: string\n): string {\n if (\n typeof value !== \"string\" ||\n value.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must be a non-empty string.\"\n );\n }\n return value.trim();\n}\n\nfunction requirePositiveFinite(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n value <= 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must be finite and greater than zero.\"\n );\n }\n return value;\n}\n\nfunction parseRange(\n value: unknown,\n path: string\n): IsoExposureIndexRange {\n const record =\n requireRecord(value, path, [\"minimum\", \"maximum\"]);\n const minimum =\n requirePositiveFinite(\n record.minimum,\n path + \".minimum\"\n );\n const maximum =\n requirePositiveFinite(\n record.maximum,\n path + \".maximum\"\n );\n if (minimum > maximum) {\n throw new InvalidConfigurationError(\n path +\n \".minimum must be less than or equal to maximum.\"\n );\n }\n return {\n minimum,\n maximum\n };\n}\n\nfunction rangeWithin(\n inner:\n IsoExposureIndexRange,\n outer:\n IsoExposureIndexRange\n): boolean {\n return (\n inner.minimum >=\n outer.minimum &&\n inner.maximum <=\n outer.maximum\n );\n}\n\nfunction parseGrid(\n value: unknown,\n range:\n IsoExposureIndexRange,\n path: string\n): IsoStandardSettingGrid {\n const record =\n requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", { \"continuous-within-range\": [\"kind\"], \"discrete-values\": [\"kind\", \"values\"] }, path);\n if (\n record.kind ===\n \"continuous-within-range\"\n ) {\n return {\n kind:\n \"continuous-within-range\"\n };\n }\n if (\n record.kind ===\n \"discrete-values\"\n ) {\n if (\n !Array.isArray(\n record.values\n ) ||\n record.values.length === 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must be a non-empty array.\"\n );\n }\n let previous =\n Number.NEGATIVE_INFINITY;\n const values =\n record.values.map(\n (entry, index) => {\n const parsed =\n requirePositiveFinite(\n entry,\n path +\n \".values[\" +\n index +\n \"]\"\n );\n if (\n parsed <= previous\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must be strictly increasing.\"\n );\n }\n if (\n parsed <\n range.minimum ||\n parsed >\n range.maximum\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must remain inside the standard ISO range.\"\n );\n }\n previous = parsed;\n return parsed;\n }\n );\n if (\n values[0] !==\n range.minimum ||\n values[\n values.length - 1\n ] !== range.maximum\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must include the exact standard range endpoints.\"\n );\n }\n return {\n kind:\n \"discrete-values\",\n values\n };\n }\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseAvailability(\n value: unknown,\n path: string\n): IsoCapabilityAvailability {\n if (\n value !== \"supported\" &&\n value !== \"unsupported\" &&\n value !== \"unknown\"\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value;\n}\n\nfunction parseAutoIso(\n value: unknown,\n standardRange:\n IsoExposureIndexRange,\n path: string\n): IsoAutoIsoCapability {\n const record =\n requireRecord(value, path, [\"availability\", \"evidence\", \"standardExposureIndexRange\"]);\n const availability =\n parseAvailability(\n record.availability,\n path + \".availability\"\n );\n const evidence =\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n );\n\n if (\n availability ===\n \"supported\"\n ) {\n const autoRange =\n parseRange(\n record\n .standardExposureIndexRange,\n path +\n \".standardExposureIndexRange\"\n );\n if (\n !rangeWithin(\n autoRange,\n standardRange\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".standardExposureIndexRange must lie inside the standard ISO range.\"\n );\n }\n return {\n availability:\n \"supported\",\n standardExposureIndexRange:\n autoRange,\n evidence\n };\n }\n\n if (\n record\n .standardExposureIndexRange !==\n undefined\n ) {\n throw new InvalidConfigurationError(\n path +\n \".standardExposureIndexRange must be omitted unless Auto ISO is supported.\"\n );\n }\n\n return {\n availability,\n evidence\n };\n}\n\nfunction parseExpandedSetting(\n value: unknown,\n standardRange:\n IsoExposureIndexRange,\n path: string\n): IsoExpandedSetting {\n const record =\n requireRecord(value, path, [\"direction\", \"exposureIndexEquivalent\", \"autoIsoEligible\", \"settingId\", \"label\", \"evidence\"]);\n const direction =\n record.direction;\n if (\n direction !== \"low\" &&\n direction !== \"high\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \".direction must be low or high.\"\n );\n }\n const exposureIndexEquivalent =\n requirePositiveFinite(\n record\n .exposureIndexEquivalent,\n path +\n \".exposureIndexEquivalent\"\n );\n if (\n (\n direction === \"low\" &&\n exposureIndexEquivalent >=\n standardRange.minimum\n ) ||\n (\n direction === \"high\" &&\n exposureIndexEquivalent <=\n standardRange.maximum\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".exposureIndexEquivalent must lie outside the standard range in the declared direction.\"\n );\n }\n if (\n typeof record.autoIsoEligible !==\n \"boolean\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \".autoIsoEligible must be boolean.\"\n );\n }\n\n return {\n settingId:\n requireNonEmptyString(\n record.settingId,\n path + \".settingId\"\n ),\n label:\n requireNonEmptyString(\n record.label,\n path + \".label\"\n ),\n direction,\n exposureIndexEquivalent,\n autoIsoEligible:\n record.autoIsoEligible,\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\nfunction parseCaptureModePolicy(\n value: unknown,\n standardRange:\n IsoExposureIndexRange,\n expandedIds:\n ReadonlySet<string>,\n path: string\n): IsoCaptureModePolicy {\n const record =\n requireRecord(value, path, [\"standardExposureIndexRange\", \"expandedSettingIds\", \"captureModeId\", \"autoIso\", \"evidence\"]);\n const modeRange =\n parseRange(\n record\n .standardExposureIndexRange,\n path +\n \".standardExposureIndexRange\"\n );\n if (\n !rangeWithin(\n modeRange,\n standardRange\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".standardExposureIndexRange must lie inside the global standard range.\"\n );\n }\n if (\n !Array.isArray(\n record.expandedSettingIds\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".expandedSettingIds must be an array.\"\n );\n }\n const expandedSettingIds =\n record.expandedSettingIds.map(\n (entry, index) => {\n const id =\n requireNonEmptyString(\n entry,\n path +\n \".expandedSettingIds[\" +\n index +\n \"]\"\n );\n if (!expandedIds.has(id)) {\n throw new InvalidConfigurationError(\n path +\n \".expandedSettingIds contains an unknown settingId.\"\n );\n }\n return id;\n }\n );\n if (\n new Set(\n expandedSettingIds\n ).size !==\n expandedSettingIds.length\n ) {\n throw new InvalidConfigurationError(\n path +\n \".expandedSettingIds must not contain duplicates.\"\n );\n }\n\n return {\n captureModeId:\n requireNonEmptyString(\n record.captureModeId,\n path + \".captureModeId\"\n ),\n standardExposureIndexRange:\n modeRange,\n expandedSettingIds,\n autoIso:\n parseAutoIso(\n record.autoIso,\n modeRange,\n path + \".autoIso\"\n ),\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\n/**\n * Validates an untrusted declaration and returns the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected here.\n *\n * ISO is an exposure-index (EI) control setting. It does not create photons and says nothing about\n * read noise. Standard and expanded settings, limits per capture mode, and whether Auto ISO is\n * available are all stated explicitly. If availability is unknown, automatic control is not allowed.\n * @param value - unknown. Untrusted input; TypeScript types alone are not validation.\n * @returns IsoCapabilityProfile. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function parseIsoCapabilityProfile(\n value: unknown\n): IsoCapabilityProfile {\n const record =\n requireRecord(\n value,\n \"isoCapabilityProfile\", [\"schemaVersion\", \"capabilityMeaning\", \"standard\", \"expandedSettings\", \"captureModePolicies\", \"profileId\", \"profileVersion\", \"autoIso\", \"evidence\"]\n );\n if (\n record.schemaVersion !==\n ISO_CAPABILITY_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'isoCapabilityProfile.schemaVersion must be \"' +\n ISO_CAPABILITY_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n if (\n record.capabilityMeaning !==\n \"reported-exposure-index-capability-not-physical-gain\"\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.capabilityMeaning is invalid.\"\n );\n }\n const standard =\n requireRecord(\n record.standard,\n \"isoCapabilityProfile.standard\", [\"exposureIndexRange\", \"settingGrid\"]\n );\n const standardRange =\n parseRange(\n standard\n .exposureIndexRange,\n \"isoCapabilityProfile.standard.exposureIndexRange\"\n );\n const settingGrid =\n parseGrid(\n standard.settingGrid,\n standardRange,\n \"isoCapabilityProfile.standard.settingGrid\"\n );\n\n if (\n !Array.isArray(\n record.expandedSettings\n )\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.expandedSettings must be an array.\"\n );\n }\n const expandedSettings =\n record.expandedSettings.map(\n (entry, index) =>\n parseExpandedSetting(\n entry,\n standardRange,\n \"isoCapabilityProfile.expandedSettings[\" +\n index +\n \"]\"\n )\n );\n const expandedIds =\n expandedSettings.map(\n (entry) =>\n entry.settingId\n );\n if (\n new Set(expandedIds).size !==\n expandedIds.length\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.expandedSettings must not contain duplicate settingId values.\"\n );\n }\n const expandedIdSet =\n new Set(expandedIds);\n\n if (\n !Array.isArray(\n record.captureModePolicies\n )\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.captureModePolicies must be an array.\"\n );\n }\n const captureModePolicies =\n record.captureModePolicies.map(\n (entry, index) =>\n parseCaptureModePolicy(\n entry,\n standardRange,\n expandedIdSet,\n \"isoCapabilityProfile.captureModePolicies[\" +\n index +\n \"]\"\n )\n );\n const modeIds =\n captureModePolicies.map(\n (entry) =>\n entry.captureModeId\n );\n if (\n new Set(modeIds).size !==\n modeIds.length\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.captureModePolicies must not contain duplicate captureModeId values.\"\n );\n }\n\n return {\n schemaVersion:\n ISO_CAPABILITY_PROFILE_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"isoCapabilityProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"isoCapabilityProfile.profileVersion\"\n ),\n capabilityMeaning:\n \"reported-exposure-index-capability-not-physical-gain\",\n standard: {\n exposureIndexRange:\n standardRange,\n settingGrid\n },\n expandedSettings,\n autoIso:\n parseAutoIso(\n record.autoIso,\n standardRange,\n \"isoCapabilityProfile.autoIso\"\n ),\n captureModePolicies,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"isoCapabilityProfile.evidence\"\n )\n };\n}\n\nfunction isStandardValueSupported(\n value: number,\n range:\n IsoExposureIndexRange,\n grid:\n IsoStandardSettingGrid\n): boolean {\n if (\n value < range.minimum ||\n value > range.maximum\n ) {\n return false;\n }\n return (\n grid.kind ===\n \"continuous-within-range\" ||\n grid.values.includes(value)\n );\n}\n\nfunction resolveModePolicy(\n profile:\n IsoCapabilityProfile,\n captureModeId:\n string | undefined\n): {\n range:\n IsoExposureIndexRange;\n expandedSettingIds:\n ReadonlySet<string>;\n autoIso:\n IsoAutoIsoCapability;\n} {\n if (\n captureModeId ===\n undefined\n ) {\n return {\n range:\n profile.standard\n .exposureIndexRange,\n expandedSettingIds:\n new Set(\n profile\n .expandedSettings\n .map(\n (entry) =>\n entry.settingId\n )\n ),\n autoIso:\n profile.autoIso\n };\n }\n if (\n captureModeId.trim()\n .length === 0\n ) {\n throw new InvalidConfigurationError(\n \"captureModeId must be a non-empty string when provided.\"\n );\n }\n const policy =\n profile.captureModePolicies.find(\n (entry) =>\n entry.captureModeId ===\n captureModeId\n );\n if (policy === undefined) {\n return {\n range:\n profile.standard\n .exposureIndexRange,\n expandedSettingIds:\n new Set(\n profile\n .expandedSettings\n .map(\n (entry) =>\n entry.settingId\n )\n ),\n autoIso:\n profile.autoIso\n };\n }\n return {\n range:\n policy\n .standardExposureIndexRange,\n expandedSettingIds:\n new Set(\n policy\n .expandedSettingIds\n ),\n autoIso:\n policy.autoIso\n };\n}\n\n/**\n * Resolves one standard, expanded or Auto ISO request against what the profile and capture mode\n * declare as available. Reports \"unavailable\" or \"unknown\" explicitly.\n *\n * ISO is an exposure-index (EI) control setting. It does not create photons and says nothing about\n * read noise. Standard and expanded settings, limits per capture mode, and whether Auto ISO is\n * available are all stated explicitly. If availability is unknown, automatic control is not allowed.\n * @param input - ResolveIsoCapabilityInput. See that type for coordinates, units and profile binding.\n * @returns ResolvedIsoCapability. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function resolveIsoCapability(\n input:\n ResolveIsoCapabilityInput\n): ResolvedIsoCapability {\n requireInputKeys(input, \"resolveIsoCapability\", [\"profile\", \"setting\", \"captureModeId\"]);\n const profile =\n parseIsoCapabilityProfile(\n input.profile\n );\n const modePolicy =\n resolveModePolicy(\n profile,\n input.captureModeId\n );\n\n if (\n input.setting.kind ===\n \"standard\"\n ) {\n if (\n typeof input.setting\n .exposureIndex !==\n \"number\" ||\n !Number.isFinite(\n input.setting\n .exposureIndex\n ) ||\n input.setting\n .exposureIndex <= 0\n ) {\n throw new InvalidScientificInputError(\n \"standard exposureIndex must be finite and greater than zero.\"\n );\n }\n if (\n !isStandardValueSupported(\n input.setting\n .exposureIndex,\n modePolicy.range,\n profile.standard\n .settingGrid\n )\n ) {\n throw new InvalidScientificInputError(\n \"Requested standard exposure index is not supported by the selected ISO capability/mode.\"\n );\n }\n\n const autoEligible =\n modePolicy.autoIso\n .availability ===\n \"supported\" &&\n input.setting\n .exposureIndex >=\n modePolicy.autoIso\n .standardExposureIndexRange\n .minimum &&\n input.setting\n .exposureIndex <=\n modePolicy.autoIso\n .standardExposureIndexRange\n .maximum;\n\n return {\n profileId:\n profile.profileId,\n profileVersion:\n profile.profileVersion,\n captureModeId:\n input.captureModeId ??\n null,\n setting: {\n kind: \"standard\",\n exposureIndex:\n input.setting\n .exposureIndex\n },\n reportedExposureIndex:\n input.setting\n .exposureIndex,\n expandedSetting: false,\n autoIsoEligible:\n autoEligible,\n standardExposureIndexRange: {\n ...modePolicy.range\n },\n standardSettingGrid:\n profile.standard\n .settingGrid.kind ===\n \"continuous-within-range\"\n ? {\n kind:\n \"continuous-within-range\"\n }\n : {\n kind:\n \"discrete-values\",\n values: [\n ...profile.standard\n .settingGrid\n .values\n ]\n },\n autoIso:\n modePolicy.autoIso,\n capturedPhotonExpectationModified:\n false,\n photonShotNoiseStatisticsModified:\n false,\n physicalGainInferred:\n false,\n conversionGainInferred:\n false,\n readNoiseInferred:\n false,\n saturationInferred:\n false,\n exactCommercialCameraBehaviorClaimed:\n false\n };\n }\n\n if (\n input.setting.kind !==\n \"expanded\"\n ) {\n throw new InvalidConfigurationError(\n \"ISO setting must be a valid standard or expanded setting.\"\n );\n }\n const expandedSettingId =\n input.setting.settingId;\n if (\n typeof expandedSettingId !==\n \"string\" ||\n expandedSettingId.trim()\n .length === 0\n ) {\n throw new InvalidConfigurationError(\n \"ISO setting must be a valid standard or expanded setting.\"\n );\n }\n\n const setting =\n profile.expandedSettings.find(\n (entry) =>\n entry.settingId ===\n expandedSettingId\n );\n if (\n setting === undefined ||\n !modePolicy\n .expandedSettingIds\n .has(setting.settingId)\n ) {\n throw new InvalidScientificInputError(\n \"Requested expanded ISO setting is not supported by the selected ISO capability/mode.\"\n );\n }\n\n return {\n profileId:\n profile.profileId,\n profileVersion:\n profile.profileVersion,\n captureModeId:\n input.captureModeId ??\n null,\n setting: {\n kind: \"expanded\",\n settingId:\n setting.settingId,\n label: setting.label,\n direction:\n setting.direction,\n exposureIndexEquivalent:\n setting\n .exposureIndexEquivalent\n },\n reportedExposureIndex:\n setting\n .exposureIndexEquivalent,\n expandedSetting: true,\n autoIsoEligible:\n modePolicy.autoIso\n .availability ===\n \"supported\" &&\n setting.autoIsoEligible,\n standardExposureIndexRange: {\n ...modePolicy.range\n },\n standardSettingGrid:\n profile.standard\n .settingGrid.kind ===\n \"continuous-within-range\"\n ? {\n kind:\n \"continuous-within-range\"\n }\n : {\n kind:\n \"discrete-values\",\n values: [\n ...profile.standard\n .settingGrid.values\n ]\n },\n autoIso:\n modePolicy.autoIso,\n capturedPhotonExpectationModified:\n false,\n photonShotNoiseStatisticsModified:\n false,\n physicalGainInferred:\n false,\n conversionGainInferred:\n false,\n readNoiseInferred: false,\n saturationInferred: false,\n exactCommercialCameraBehaviorClaimed:\n false\n };\n}\n\n\nexport interface BindIsoCapabilityToExposureCapabilitiesInput {\n isoCapabilityProfile:\n IsoCapabilityProfile;\n equipmentCapabilities:\n ResolvedGenericEquipmentExposureCapabilities;\n captureModeId?: string;\n}\n\nexport interface BoundIsoExposureCapabilities {\n isoCapabilityProfileId: string;\n isoCapabilityProfileVersion: string;\n captureModeId: string | null;\n capabilities:\n ResolvedGenericEquipmentExposureCapabilities;\n expandedSettingsExcludedFromNumericExposureGrid:\n true;\n physicalGainInferred: false;\n readNoiseInferred: false;\n}\n\nfunction sameResolvedGrid(\n resolved:\n ResolvedNumericSettingGrid,\n detailed:\n IsoStandardSettingGrid\n): boolean {\n if (\n resolved.kind !==\n detailed.kind\n ) {\n return false;\n }\n if (\n resolved.kind ===\n \"continuous-within-range\" ||\n detailed.kind ===\n \"continuous-within-range\"\n ) {\n return true;\n }\n return (\n resolved.values.length ===\n detailed.values.length &&\n resolved.values.every(\n (value, index) =>\n value ===\n detailed.values[index]\n )\n );\n}\n\nfunction gridWithinRange(\n grid:\n ResolvedNumericSettingGrid,\n range:\n IsoExposureIndexRange\n): ResolvedNumericSettingGrid {\n if (\n grid.kind ===\n \"continuous-within-range\"\n ) {\n return {\n kind:\n \"continuous-within-range\"\n };\n }\n const values =\n grid.values.filter(\n (value) =>\n value >= range.minimum &&\n value <= range.maximum\n );\n if (values.length === 0) {\n throw new InvalidScientificInputError(\n \"Selected capture-mode ISO range contains no values from the resolved equipment ISO grid.\"\n );\n }\n return {\n kind: \"discrete-values\",\n values\n };\n}\n\n/**\n * Combines the detailed ISO/EI capability profile with the numeric capability\n * envelope that the exposure-mode resolvers use.\n *\n * The existing equipment capability must match the profile's global standard\n * ISO range and grid exactly. A capture-mode policy backed by evidence may\n * narrow the standard manual range for that mode. Auto ISO may be narrower\n * still. Expanded settings (such as L and H) stay outside the resolvers'\n * ordinary numeric ISO grid; use resolveIsoCapability() for them.\n */\nexport function bindIsoCapabilityToExposureCapabilities(\n input:\n BindIsoCapabilityToExposureCapabilitiesInput\n): BoundIsoExposureCapabilities {\n requireInputKeys(input, \"bindIsoCapabilityToExposureCapabilities\", [\"isoCapabilityProfile\", \"equipmentCapabilities\", \"captureModeId\"]);\n const profile =\n parseIsoCapabilityProfile(\n input.isoCapabilityProfile\n );\n const source =\n input.equipmentCapabilities;\n\n if (\n source.iso.minimum !==\n profile.standard\n .exposureIndexRange\n .minimum ||\n source.iso.maximum !==\n profile.standard\n .exposureIndexRange\n .maximum ||\n !sameResolvedGrid(\n source.iso.settingGrid,\n profile.standard\n .settingGrid\n )\n ) {\n throw new InvalidScientificInputError(\n \"Detailed ISO capability standard range/grid must exactly match the existing resolved equipment ISO capability.\"\n );\n }\n\n const modePolicy =\n resolveModePolicy(\n profile,\n input.captureModeId\n );\n const settingGrid =\n gridWithinRange(\n source.iso.settingGrid,\n modePolicy.range\n );\n\n const iso =\n modePolicy.autoIso\n .availability ===\n \"supported\"\n ? {\n minimum:\n modePolicy.range.minimum,\n maximum:\n modePolicy.range.maximum,\n settingGrid,\n autoIsoAvailability:\n \"supported\" as const,\n autoIsoMinimum:\n modePolicy.autoIso\n .standardExposureIndexRange\n .minimum,\n autoIsoMaximum:\n modePolicy.autoIso\n .standardExposureIndexRange\n .maximum\n }\n : {\n minimum:\n modePolicy.range.minimum,\n maximum:\n modePolicy.range.maximum,\n settingGrid,\n autoIsoAvailability:\n modePolicy.autoIso\n .availability\n };\n\n return {\n isoCapabilityProfileId:\n profile.profileId,\n isoCapabilityProfileVersion:\n profile.profileVersion,\n captureModeId:\n input.captureModeId ??\n null,\n capabilities: {\n ...source,\n iso\n },\n expandedSettingsExcludedFromNumericExposureGrid:\n true,\n physicalGainInferred:\n false,\n readNoiseInferred:\n false\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"iso-capabilities.js","sourceRoot":"","sources":["../../src/equipment/iso-capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * ISO capabilities: which standard, expanded and Auto ISO settings a body offers, and in which\n * capture modes.\n *\n * The parser validates untrusted input and returns the normalized typed contract. Unknown enum\n * values, missing required fields and incompatible scientific data are rejected.\n *\n * ISO is an exposure-index (EI) control setting. It does not create photons and says nothing about\n * read noise. Standard and expanded settings, limits per capture mode, and whether Auto ISO is\n * available are all stated explicitly. If availability is unknown, automatic control is not allowed.\n * @see docs/GENERIC_TIER_PRESETS.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport type {\n ResolvedGenericEquipmentExposureCapabilities,\n ResolvedNumericSettingGrid\n} from \"./exposure-capabilities.js\";\nimport { requireInputKeys, rejectUnknownVariantFields, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, requireConfigPositiveFinite as requirePositiveFinite, parseConfigAvailability as parseAvailability } from \"../core/record-validation.js\";\nimport { parseRange } from \"./exposure-capabilities.js\";\n\nexport const ISO_CAPABILITY_PROFILE_SCHEMA_VERSION =\n \"0.1.0\" as const;\n\nexport type IsoCapabilityAvailability =\n | \"supported\"\n | \"unsupported\"\n | \"unknown\";\n\nexport interface IsoExposureIndexRange {\n minimum: number;\n maximum: number;\n}\n\nexport type IsoStandardSettingGrid =\n | {\n kind: \"continuous-within-range\";\n }\n | {\n kind: \"discrete-values\";\n values: readonly number[];\n };\n\nexport interface IsoExpandedSetting {\n settingId: string;\n label: string;\n direction: \"low\" | \"high\";\n exposureIndexEquivalent: number;\n autoIsoEligible: boolean;\n evidence: readonly EvidenceProvenance[];\n}\n\nexport type IsoAutoIsoCapability =\n | {\n availability: \"supported\";\n standardExposureIndexRange:\n IsoExposureIndexRange;\n evidence: readonly EvidenceProvenance[];\n }\n | {\n availability:\n | \"unsupported\"\n | \"unknown\";\n evidence: readonly EvidenceProvenance[];\n };\n\nexport interface IsoCaptureModePolicy {\n captureModeId: string;\n standardExposureIndexRange:\n IsoExposureIndexRange;\n expandedSettingIds:\n readonly string[];\n autoIso:\n IsoAutoIsoCapability;\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface IsoCapabilityProfile {\n schemaVersion:\n typeof ISO_CAPABILITY_PROFILE_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n capabilityMeaning:\n \"reported-exposure-index-capability-not-physical-gain\";\n standard: {\n exposureIndexRange:\n IsoExposureIndexRange;\n settingGrid:\n IsoStandardSettingGrid;\n };\n expandedSettings:\n readonly IsoExpandedSetting[];\n autoIso:\n IsoAutoIsoCapability;\n captureModePolicies:\n readonly IsoCaptureModePolicy[];\n evidence:\n readonly EvidenceProvenance[];\n}\n\nexport type RequestedIsoSetting =\n | {\n kind: \"standard\";\n exposureIndex: number;\n }\n | {\n kind: \"expanded\";\n settingId: string;\n };\n\nexport interface ResolveIsoCapabilityInput {\n profile:\n IsoCapabilityProfile;\n setting:\n RequestedIsoSetting;\n captureModeId?: string;\n}\n\nexport interface ResolvedIsoCapability {\n profileId: string;\n profileVersion: string;\n captureModeId: string | null;\n setting:\n | {\n kind: \"standard\";\n exposureIndex: number;\n }\n | {\n kind: \"expanded\";\n settingId: string;\n label: string;\n direction:\n \"low\" | \"high\";\n exposureIndexEquivalent:\n number;\n };\n reportedExposureIndex: number;\n expandedSetting: boolean;\n autoIsoEligible:\n boolean;\n standardExposureIndexRange:\n IsoExposureIndexRange;\n standardSettingGrid:\n IsoStandardSettingGrid;\n autoIso:\n IsoAutoIsoCapability;\n capturedPhotonExpectationModified:\n false;\n photonShotNoiseStatisticsModified:\n false;\n physicalGainInferred:\n false;\n conversionGainInferred:\n false;\n readNoiseInferred: false;\n saturationInferred: false;\n exactCommercialCameraBehaviorClaimed:\n false;\n}\n\nfunction rangeWithin(\n inner:\n IsoExposureIndexRange,\n outer:\n IsoExposureIndexRange\n): boolean {\n return (\n inner.minimum >=\n outer.minimum &&\n inner.maximum <=\n outer.maximum\n );\n}\n\nfunction parseGrid(\n value: unknown,\n range:\n IsoExposureIndexRange,\n path: string\n): IsoStandardSettingGrid {\n const record =\n requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", { \"continuous-within-range\": [\"kind\"], \"discrete-values\": [\"kind\", \"values\"] }, path);\n if (\n record.kind ===\n \"continuous-within-range\"\n ) {\n return {\n kind:\n \"continuous-within-range\"\n };\n }\n if (\n record.kind ===\n \"discrete-values\"\n ) {\n if (\n !Array.isArray(\n record.values\n ) ||\n record.values.length === 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must be a non-empty array.\"\n );\n }\n let previous =\n Number.NEGATIVE_INFINITY;\n const values =\n record.values.map(\n (entry, index) => {\n const parsed =\n requirePositiveFinite(\n entry,\n path +\n \".values[\" +\n index +\n \"]\"\n );\n if (\n parsed <= previous\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must be strictly increasing.\"\n );\n }\n if (\n parsed <\n range.minimum ||\n parsed >\n range.maximum\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must remain inside the standard ISO range.\"\n );\n }\n previous = parsed;\n return parsed;\n }\n );\n if (\n values[0] !==\n range.minimum ||\n values[\n values.length - 1\n ] !== range.maximum\n ) {\n throw new InvalidConfigurationError(\n path +\n \".values must include the exact standard range endpoints.\"\n );\n }\n return {\n kind:\n \"discrete-values\",\n values\n };\n }\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseAutoIso(\n value: unknown,\n standardRange:\n IsoExposureIndexRange,\n path: string\n): IsoAutoIsoCapability {\n const record =\n requireRecord(value, path, [\"availability\", \"evidence\", \"standardExposureIndexRange\"]);\n const availability =\n parseAvailability(\n record.availability,\n path + \".availability\"\n );\n const evidence =\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n );\n\n if (\n availability ===\n \"supported\"\n ) {\n const autoRange =\n parseRange(\n record\n .standardExposureIndexRange,\n path +\n \".standardExposureIndexRange\"\n );\n if (\n !rangeWithin(\n autoRange,\n standardRange\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".standardExposureIndexRange must lie inside the standard ISO range.\"\n );\n }\n return {\n availability:\n \"supported\",\n standardExposureIndexRange:\n autoRange,\n evidence\n };\n }\n\n if (\n record\n .standardExposureIndexRange !==\n undefined\n ) {\n throw new InvalidConfigurationError(\n path +\n \".standardExposureIndexRange must be omitted unless Auto ISO is supported.\"\n );\n }\n\n return {\n availability,\n evidence\n };\n}\n\nfunction parseExpandedSetting(\n value: unknown,\n standardRange:\n IsoExposureIndexRange,\n path: string\n): IsoExpandedSetting {\n const record =\n requireRecord(value, path, [\"direction\", \"exposureIndexEquivalent\", \"autoIsoEligible\", \"settingId\", \"label\", \"evidence\"]);\n const direction =\n record.direction;\n if (\n direction !== \"low\" &&\n direction !== \"high\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \".direction must be low or high.\"\n );\n }\n const exposureIndexEquivalent =\n requirePositiveFinite(\n record\n .exposureIndexEquivalent,\n path +\n \".exposureIndexEquivalent\"\n );\n if (\n (\n direction === \"low\" &&\n exposureIndexEquivalent >=\n standardRange.minimum\n ) ||\n (\n direction === \"high\" &&\n exposureIndexEquivalent <=\n standardRange.maximum\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".exposureIndexEquivalent must lie outside the standard range in the declared direction.\"\n );\n }\n if (\n typeof record.autoIsoEligible !==\n \"boolean\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \".autoIsoEligible must be boolean.\"\n );\n }\n\n return {\n settingId:\n requireNonEmptyString(\n record.settingId,\n path + \".settingId\"\n ),\n label:\n requireNonEmptyString(\n record.label,\n path + \".label\"\n ),\n direction,\n exposureIndexEquivalent,\n autoIsoEligible:\n record.autoIsoEligible,\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\nfunction parseCaptureModePolicy(\n value: unknown,\n standardRange:\n IsoExposureIndexRange,\n expandedIds:\n ReadonlySet<string>,\n path: string\n): IsoCaptureModePolicy {\n const record =\n requireRecord(value, path, [\"standardExposureIndexRange\", \"expandedSettingIds\", \"captureModeId\", \"autoIso\", \"evidence\"]);\n const modeRange =\n parseRange(\n record\n .standardExposureIndexRange,\n path +\n \".standardExposureIndexRange\"\n );\n if (\n !rangeWithin(\n modeRange,\n standardRange\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".standardExposureIndexRange must lie inside the global standard range.\"\n );\n }\n if (\n !Array.isArray(\n record.expandedSettingIds\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \".expandedSettingIds must be an array.\"\n );\n }\n const expandedSettingIds =\n record.expandedSettingIds.map(\n (entry, index) => {\n const id =\n requireNonEmptyString(\n entry,\n path +\n \".expandedSettingIds[\" +\n index +\n \"]\"\n );\n if (!expandedIds.has(id)) {\n throw new InvalidConfigurationError(\n path +\n \".expandedSettingIds contains an unknown settingId.\"\n );\n }\n return id;\n }\n );\n if (\n new Set(\n expandedSettingIds\n ).size !==\n expandedSettingIds.length\n ) {\n throw new InvalidConfigurationError(\n path +\n \".expandedSettingIds must not contain duplicates.\"\n );\n }\n\n return {\n captureModeId:\n requireNonEmptyString(\n record.captureModeId,\n path + \".captureModeId\"\n ),\n standardExposureIndexRange:\n modeRange,\n expandedSettingIds,\n autoIso:\n parseAutoIso(\n record.autoIso,\n modeRange,\n path + \".autoIso\"\n ),\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\n/**\n * Validates an untrusted declaration and returns the normalized typed contract. Unknown enum values,\n * missing required fields and incompatible scientific data are rejected here.\n *\n * ISO is an exposure-index (EI) control setting. It does not create photons and says nothing about\n * read noise. Standard and expanded settings, limits per capture mode, and whether Auto ISO is\n * available are all stated explicitly. If availability is unknown, automatic control is not allowed.\n * @param value - unknown. Untrusted input; TypeScript types alone are not validation.\n * @returns IsoCapabilityProfile. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function parseIsoCapabilityProfile(\n value: unknown\n): IsoCapabilityProfile {\n const record =\n requireRecord(\n value,\n \"isoCapabilityProfile\", [\"schemaVersion\", \"capabilityMeaning\", \"standard\", \"expandedSettings\", \"captureModePolicies\", \"profileId\", \"profileVersion\", \"autoIso\", \"evidence\"]\n );\n if (\n record.schemaVersion !==\n ISO_CAPABILITY_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'isoCapabilityProfile.schemaVersion must be \"' +\n ISO_CAPABILITY_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n if (\n record.capabilityMeaning !==\n \"reported-exposure-index-capability-not-physical-gain\"\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.capabilityMeaning is invalid.\"\n );\n }\n const standard =\n requireRecord(\n record.standard,\n \"isoCapabilityProfile.standard\", [\"exposureIndexRange\", \"settingGrid\"]\n );\n const standardRange =\n parseRange(\n standard\n .exposureIndexRange,\n \"isoCapabilityProfile.standard.exposureIndexRange\"\n );\n const settingGrid =\n parseGrid(\n standard.settingGrid,\n standardRange,\n \"isoCapabilityProfile.standard.settingGrid\"\n );\n\n if (\n !Array.isArray(\n record.expandedSettings\n )\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.expandedSettings must be an array.\"\n );\n }\n const expandedSettings =\n record.expandedSettings.map(\n (entry, index) =>\n parseExpandedSetting(\n entry,\n standardRange,\n \"isoCapabilityProfile.expandedSettings[\" +\n index +\n \"]\"\n )\n );\n const expandedIds =\n expandedSettings.map(\n (entry) =>\n entry.settingId\n );\n if (\n new Set(expandedIds).size !==\n expandedIds.length\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.expandedSettings must not contain duplicate settingId values.\"\n );\n }\n const expandedIdSet =\n new Set(expandedIds);\n\n if (\n !Array.isArray(\n record.captureModePolicies\n )\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.captureModePolicies must be an array.\"\n );\n }\n const captureModePolicies =\n record.captureModePolicies.map(\n (entry, index) =>\n parseCaptureModePolicy(\n entry,\n standardRange,\n expandedIdSet,\n \"isoCapabilityProfile.captureModePolicies[\" +\n index +\n \"]\"\n )\n );\n const modeIds =\n captureModePolicies.map(\n (entry) =>\n entry.captureModeId\n );\n if (\n new Set(modeIds).size !==\n modeIds.length\n ) {\n throw new InvalidConfigurationError(\n \"isoCapabilityProfile.captureModePolicies must not contain duplicate captureModeId values.\"\n );\n }\n\n return {\n schemaVersion:\n ISO_CAPABILITY_PROFILE_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"isoCapabilityProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"isoCapabilityProfile.profileVersion\"\n ),\n capabilityMeaning:\n \"reported-exposure-index-capability-not-physical-gain\",\n standard: {\n exposureIndexRange:\n standardRange,\n settingGrid\n },\n expandedSettings,\n autoIso:\n parseAutoIso(\n record.autoIso,\n standardRange,\n \"isoCapabilityProfile.autoIso\"\n ),\n captureModePolicies,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"isoCapabilityProfile.evidence\"\n )\n };\n}\n\nfunction isStandardValueSupported(\n value: number,\n range:\n IsoExposureIndexRange,\n grid:\n IsoStandardSettingGrid\n): boolean {\n if (\n value < range.minimum ||\n value > range.maximum\n ) {\n return false;\n }\n return (\n grid.kind ===\n \"continuous-within-range\" ||\n grid.values.includes(value)\n );\n}\n\nfunction resolveModePolicy(\n profile:\n IsoCapabilityProfile,\n captureModeId:\n string | undefined\n): {\n range:\n IsoExposureIndexRange;\n expandedSettingIds:\n ReadonlySet<string>;\n autoIso:\n IsoAutoIsoCapability;\n} {\n if (\n captureModeId ===\n undefined\n ) {\n return {\n range:\n profile.standard\n .exposureIndexRange,\n expandedSettingIds:\n new Set(\n profile\n .expandedSettings\n .map(\n (entry) =>\n entry.settingId\n )\n ),\n autoIso:\n profile.autoIso\n };\n }\n if (\n captureModeId.trim()\n .length === 0\n ) {\n throw new InvalidConfigurationError(\n \"captureModeId must be a non-empty string when provided.\"\n );\n }\n const policy =\n profile.captureModePolicies.find(\n (entry) =>\n entry.captureModeId ===\n captureModeId\n );\n if (policy === undefined) {\n return {\n range:\n profile.standard\n .exposureIndexRange,\n expandedSettingIds:\n new Set(\n profile\n .expandedSettings\n .map(\n (entry) =>\n entry.settingId\n )\n ),\n autoIso:\n profile.autoIso\n };\n }\n return {\n range:\n policy\n .standardExposureIndexRange,\n expandedSettingIds:\n new Set(\n policy\n .expandedSettingIds\n ),\n autoIso:\n policy.autoIso\n };\n}\n\n/**\n * Resolves one standard, expanded or Auto ISO request against what the profile and capture mode\n * declare as available. Reports \"unavailable\" or \"unknown\" explicitly.\n *\n * ISO is an exposure-index (EI) control setting. It does not create photons and says nothing about\n * read noise. Standard and expanded settings, limits per capture mode, and whether Auto ISO is\n * available are all stated explicitly. If availability is unknown, automatic control is not allowed.\n * @param input - ResolveIsoCapabilityInput. See that type for coordinates, units and profile binding.\n * @returns ResolvedIsoCapability. The result states its shape and scientific status; a successful call does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the root export and exact type graph.\n */\nexport function resolveIsoCapability(\n input:\n ResolveIsoCapabilityInput\n): ResolvedIsoCapability {\n requireInputKeys(input, \"resolveIsoCapability\", [\"profile\", \"setting\", \"captureModeId\"]);\n const profile =\n parseIsoCapabilityProfile(\n input.profile\n );\n const modePolicy =\n resolveModePolicy(\n profile,\n input.captureModeId\n );\n\n if (\n input.setting.kind ===\n \"standard\"\n ) {\n if (\n typeof input.setting\n .exposureIndex !==\n \"number\" ||\n !Number.isFinite(\n input.setting\n .exposureIndex\n ) ||\n input.setting\n .exposureIndex <= 0\n ) {\n throw new InvalidScientificInputError(\n \"standard exposureIndex must be finite and greater than zero.\"\n );\n }\n if (\n !isStandardValueSupported(\n input.setting\n .exposureIndex,\n modePolicy.range,\n profile.standard\n .settingGrid\n )\n ) {\n throw new InvalidScientificInputError(\n \"Requested standard exposure index is not supported by the selected ISO capability/mode.\"\n );\n }\n\n const autoEligible =\n modePolicy.autoIso\n .availability ===\n \"supported\" &&\n input.setting\n .exposureIndex >=\n modePolicy.autoIso\n .standardExposureIndexRange\n .minimum &&\n input.setting\n .exposureIndex <=\n modePolicy.autoIso\n .standardExposureIndexRange\n .maximum;\n\n return {\n profileId:\n profile.profileId,\n profileVersion:\n profile.profileVersion,\n captureModeId:\n input.captureModeId ??\n null,\n setting: {\n kind: \"standard\",\n exposureIndex:\n input.setting\n .exposureIndex\n },\n reportedExposureIndex:\n input.setting\n .exposureIndex,\n expandedSetting: false,\n autoIsoEligible:\n autoEligible,\n standardExposureIndexRange: {\n ...modePolicy.range\n },\n standardSettingGrid:\n profile.standard\n .settingGrid.kind ===\n \"continuous-within-range\"\n ? {\n kind:\n \"continuous-within-range\"\n }\n : {\n kind:\n \"discrete-values\",\n values: [\n ...profile.standard\n .settingGrid\n .values\n ]\n },\n autoIso:\n modePolicy.autoIso,\n capturedPhotonExpectationModified:\n false,\n photonShotNoiseStatisticsModified:\n false,\n physicalGainInferred:\n false,\n conversionGainInferred:\n false,\n readNoiseInferred:\n false,\n saturationInferred:\n false,\n exactCommercialCameraBehaviorClaimed:\n false\n };\n }\n\n if (\n input.setting.kind !==\n \"expanded\"\n ) {\n throw new InvalidConfigurationError(\n \"ISO setting must be a valid standard or expanded setting.\"\n );\n }\n const expandedSettingId =\n input.setting.settingId;\n if (\n typeof expandedSettingId !==\n \"string\" ||\n expandedSettingId.trim()\n .length === 0\n ) {\n throw new InvalidConfigurationError(\n \"ISO setting must be a valid standard or expanded setting.\"\n );\n }\n\n const setting =\n profile.expandedSettings.find(\n (entry) =>\n entry.settingId ===\n expandedSettingId\n );\n if (\n setting === undefined ||\n !modePolicy\n .expandedSettingIds\n .has(setting.settingId)\n ) {\n throw new InvalidScientificInputError(\n \"Requested expanded ISO setting is not supported by the selected ISO capability/mode.\"\n );\n }\n\n return {\n profileId:\n profile.profileId,\n profileVersion:\n profile.profileVersion,\n captureModeId:\n input.captureModeId ??\n null,\n setting: {\n kind: \"expanded\",\n settingId:\n setting.settingId,\n label: setting.label,\n direction:\n setting.direction,\n exposureIndexEquivalent:\n setting\n .exposureIndexEquivalent\n },\n reportedExposureIndex:\n setting\n .exposureIndexEquivalent,\n expandedSetting: true,\n autoIsoEligible:\n modePolicy.autoIso\n .availability ===\n \"supported\" &&\n setting.autoIsoEligible,\n standardExposureIndexRange: {\n ...modePolicy.range\n },\n standardSettingGrid:\n profile.standard\n .settingGrid.kind ===\n \"continuous-within-range\"\n ? {\n kind:\n \"continuous-within-range\"\n }\n : {\n kind:\n \"discrete-values\",\n values: [\n ...profile.standard\n .settingGrid.values\n ]\n },\n autoIso:\n modePolicy.autoIso,\n capturedPhotonExpectationModified:\n false,\n photonShotNoiseStatisticsModified:\n false,\n physicalGainInferred:\n false,\n conversionGainInferred:\n false,\n readNoiseInferred: false,\n saturationInferred: false,\n exactCommercialCameraBehaviorClaimed:\n false\n };\n}\n\nexport interface BindIsoCapabilityToExposureCapabilitiesInput {\n isoCapabilityProfile:\n IsoCapabilityProfile;\n equipmentCapabilities:\n ResolvedGenericEquipmentExposureCapabilities;\n captureModeId?: string;\n}\n\nexport interface BoundIsoExposureCapabilities {\n isoCapabilityProfileId: string;\n isoCapabilityProfileVersion: string;\n captureModeId: string | null;\n capabilities:\n ResolvedGenericEquipmentExposureCapabilities;\n expandedSettingsExcludedFromNumericExposureGrid:\n true;\n physicalGainInferred: false;\n readNoiseInferred: false;\n}\n\nfunction sameResolvedGrid(\n resolved:\n ResolvedNumericSettingGrid,\n detailed:\n IsoStandardSettingGrid\n): boolean {\n if (\n resolved.kind !==\n detailed.kind\n ) {\n return false;\n }\n if (\n resolved.kind ===\n \"continuous-within-range\" ||\n detailed.kind ===\n \"continuous-within-range\"\n ) {\n return true;\n }\n return (\n resolved.values.length ===\n detailed.values.length &&\n resolved.values.every(\n (value, index) =>\n value ===\n detailed.values[index]\n )\n );\n}\n\nfunction gridWithinRange(\n grid:\n ResolvedNumericSettingGrid,\n range:\n IsoExposureIndexRange\n): ResolvedNumericSettingGrid {\n if (\n grid.kind ===\n \"continuous-within-range\"\n ) {\n return {\n kind:\n \"continuous-within-range\"\n };\n }\n const values =\n grid.values.filter(\n (value) =>\n value >= range.minimum &&\n value <= range.maximum\n );\n if (values.length === 0) {\n throw new InvalidScientificInputError(\n \"Selected capture-mode ISO range contains no values from the resolved equipment ISO grid.\"\n );\n }\n return {\n kind: \"discrete-values\",\n values\n };\n}\n\n/**\n * Combines the detailed ISO/EI capability profile with the numeric capability\n * envelope that the exposure-mode resolvers use.\n *\n * The existing equipment capability must match the profile's global standard\n * ISO range and grid exactly. A capture-mode policy backed by evidence may\n * narrow the standard manual range for that mode. Auto ISO may be narrower\n * still. Expanded settings (such as L and H) stay outside the resolvers'\n * ordinary numeric ISO grid; use resolveIsoCapability() for them.\n */\nexport function bindIsoCapabilityToExposureCapabilities(\n input:\n BindIsoCapabilityToExposureCapabilitiesInput\n): BoundIsoExposureCapabilities {\n requireInputKeys(input, \"bindIsoCapabilityToExposureCapabilities\", [\"isoCapabilityProfile\", \"equipmentCapabilities\", \"captureModeId\"]);\n const profile =\n parseIsoCapabilityProfile(\n input.isoCapabilityProfile\n );\n const source =\n input.equipmentCapabilities;\n\n if (\n source.iso.minimum !==\n profile.standard\n .exposureIndexRange\n .minimum ||\n source.iso.maximum !==\n profile.standard\n .exposureIndexRange\n .maximum ||\n !sameResolvedGrid(\n source.iso.settingGrid,\n profile.standard\n .settingGrid\n )\n ) {\n throw new InvalidScientificInputError(\n \"Detailed ISO capability standard range/grid must exactly match the existing resolved equipment ISO capability.\"\n );\n }\n\n const modePolicy =\n resolveModePolicy(\n profile,\n input.captureModeId\n );\n const settingGrid =\n gridWithinRange(\n source.iso.settingGrid,\n modePolicy.range\n );\n\n const iso =\n modePolicy.autoIso\n .availability ===\n \"supported\"\n ? {\n minimum:\n modePolicy.range.minimum,\n maximum:\n modePolicy.range.maximum,\n settingGrid,\n autoIsoAvailability:\n \"supported\" as const,\n autoIsoMinimum:\n modePolicy.autoIso\n .standardExposureIndexRange\n .minimum,\n autoIsoMaximum:\n modePolicy.autoIso\n .standardExposureIndexRange\n .maximum\n }\n : {\n minimum:\n modePolicy.range.minimum,\n maximum:\n modePolicy.range.maximum,\n settingGrid,\n autoIsoAvailability:\n modePolicy.autoIso\n .availability\n };\n\n return {\n isoCapabilityProfileId:\n profile.profileId,\n isoCapabilityProfileVersion:\n profile.profileVersion,\n captureModeId:\n input.captureModeId ??\n null,\n capabilities: {\n ...source,\n iso\n },\n expandedSettingsExcludedFromNumericExposureGrid:\n true,\n physicalGainInferred:\n false,\n readNoiseInferred:\n false\n };\n}\n"]}
|
|
@@ -12,7 +12,7 @@ import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
|
12
12
|
import { parseEvidenceList } from "../core/evidence-provenance.js";
|
|
13
13
|
import { InvalidScientificInputError } from "../core/validation.js";
|
|
14
14
|
import { parseExposureMeteringProfile } from "../exposure/metering.js";
|
|
15
|
-
import { requireInputKeys,
|
|
15
|
+
import { requireInputKeys, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, parseConfigAvailability as parseAvailability } from "../core/record-validation.js";
|
|
16
16
|
export const GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION = "0.1.0";
|
|
17
17
|
const POLICY_KINDS = new Set([
|
|
18
18
|
"multi-zone-uniform",
|
|
@@ -21,31 +21,6 @@ const POLICY_KINDS = new Set([
|
|
|
21
21
|
"highlight-weighted",
|
|
22
22
|
"highlight-priority"
|
|
23
23
|
]);
|
|
24
|
-
function requireRecord(value, path, allowedKeys) {
|
|
25
|
-
if (typeof value !== "object" ||
|
|
26
|
-
value === null ||
|
|
27
|
-
Array.isArray(value)) {
|
|
28
|
-
throw new InvalidConfigurationError(path + " must be an object.");
|
|
29
|
-
}
|
|
30
|
-
if (allowedKeys !== null)
|
|
31
|
-
rejectUnknownFields(value, allowedKeys, path);
|
|
32
|
-
return value;
|
|
33
|
-
}
|
|
34
|
-
function requireNonEmptyString(value, path) {
|
|
35
|
-
if (typeof value !== "string" ||
|
|
36
|
-
value.trim().length === 0) {
|
|
37
|
-
throw new InvalidConfigurationError(path + " must be a non-empty string.");
|
|
38
|
-
}
|
|
39
|
-
return value.trim();
|
|
40
|
-
}
|
|
41
|
-
function parseAvailability(value, path) {
|
|
42
|
-
if (value !== "supported" &&
|
|
43
|
-
value !== "unsupported" &&
|
|
44
|
-
value !== "unknown") {
|
|
45
|
-
throw new InvalidConfigurationError(path + " is invalid.");
|
|
46
|
-
}
|
|
47
|
-
return value;
|
|
48
|
-
}
|
|
49
24
|
function parsePolicyKind(value, path) {
|
|
50
25
|
if (typeof value !== "string" ||
|
|
51
26
|
!POLICY_KINDS.has(value)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metering-capabilities.js","sourceRoot":"","sources":["../../src/equipment/metering-capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Metering capabilities of a generic body: which of the engine's metering profiles and modes it can\n * select.\n *\n * This profile deliberately does not copy target or calibration values from those metering profiles.\n * The metering profile stays the single source of its calibration and target policy.\n * @see docs/GENERIC_TIER_PRESETS.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport {\n parseExposureMeteringProfile,\n type ExposureMeteringPolicy,\n type ExposureMeteringProfile\n} from \"../exposure/metering.js\";\nimport type { GenericCapabilityAvailability } from \"./exposure-capabilities.js\";\nimport { requireInputKeys, rejectUnknownFields } from \"../core/record-validation.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport const GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION =\n \"0.1.0\" as const;\n\nexport interface GenericSupportedMeteringProfile {\n meteringProfileId: string;\n policyKind: ExposureMeteringPolicy[\"kind\"];\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface GenericBodyMeteringCapabilityProfile {\n schemaVersion:\n typeof GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n scientificStatus: \"approximation\";\n evidence: readonly EvidenceProvenance[];\n supportedMeteringProfiles:\n readonly GenericSupportedMeteringProfile[];\n spotFocusPointLinkage: {\n availability: GenericCapabilityAvailability;\n evidence: readonly EvidenceProvenance[];\n };\n}\n\nexport type MeteringCapabilityCompatibilityBlocker =\n | \"metering-profile-unsupported\"\n | \"metering-policy-mismatch\";\n\nexport interface MeteringCapabilityCompatibilityAssessment {\n schemaVersion:\n typeof GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION;\n status: \"compatible\" | \"blocked\";\n bodyProfile: {\n profileId: string;\n profileVersion: string;\n };\n meteringProfile: {\n profileId: string;\n policyKind: ExposureMeteringPolicy[\"kind\"];\n };\n targetPolicyOwnership: \"metering-profile\";\n targetCalibrationDuplicatedInEquipmentProfile: false;\n spotFocusPointLinkageAvailability:\n GenericCapabilityAvailability;\n blockers:\n readonly MeteringCapabilityCompatibilityBlocker[];\n}\n\nexport interface AssessExposureMeteringProfileCompatibilityInput {\n bodyCapabilities:\n GenericBodyMeteringCapabilityProfile;\n meteringProfile:\n ExposureMeteringProfile;\n}\n\nconst POLICY_KINDS =\n new Set<ExposureMeteringPolicy[\"kind\"]>([\n \"multi-zone-uniform\",\n \"center-weighted-radial\",\n \"spot\",\n \"highlight-weighted\",\n \"highlight-priority\"\n ]);\n\nfunction requireRecord(\n value: unknown,\n path: string,\n allowedKeys: readonly string[] | null\n): UnknownRecord {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be an object.\"\n );\n }\n if (allowedKeys !== null) rejectUnknownFields(value, allowedKeys, path);\n return value as UnknownRecord;\n}\n\nfunction requireNonEmptyString(\n value: unknown,\n path: string\n): string {\n if (\n typeof value !== \"string\" ||\n value.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n path + \" must be a non-empty string.\"\n );\n }\n return value.trim();\n}\n\nfunction parseAvailability(\n value: unknown,\n path: string\n): GenericCapabilityAvailability {\n if (\n value !== \"supported\" &&\n value !== \"unsupported\" &&\n value !== \"unknown\"\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value;\n}\n\nfunction parsePolicyKind(\n value: unknown,\n path: string\n): ExposureMeteringPolicy[\"kind\"] {\n if (\n typeof value !== \"string\" ||\n !POLICY_KINDS.has(\n value as ExposureMeteringPolicy[\"kind\"]\n )\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value as ExposureMeteringPolicy[\"kind\"];\n}\n\n/**\n * Parses generic body metering capability metadata.\n *\n * This profile declares which of the engine's metering profiles and modes a\n * generic body can select. It deliberately does not copy target or\n * calibration values from those metering profiles.\n */\nexport function parseGenericBodyMeteringCapabilityProfile(\n value: unknown\n): GenericBodyMeteringCapabilityProfile {\n const record = requireRecord(\n value,\n \"genericBodyMeteringCapabilityProfile\", [\"schemaVersion\", \"scientificStatus\", \"supportedMeteringProfiles\", \"spotFocusPointLinkage\", \"profileId\", \"profileVersion\", \"evidence\"]\n );\n\n if (\n record.schemaVersion !==\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'genericBodyMeteringCapabilityProfile.schemaVersion must be \"' +\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION +\n '\".'\n );\n }\n if (\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n 'genericBodyMeteringCapabilityProfile.scientificStatus must be \"approximation\".'\n );\n }\n\n if (\n !Array.isArray(\n record.supportedMeteringProfiles\n ) ||\n record.supportedMeteringProfiles\n .length === 0\n ) {\n throw new InvalidConfigurationError(\n \"genericBodyMeteringCapabilityProfile.supportedMeteringProfiles must be a non-empty array.\"\n );\n }\n\n const supported =\n record.supportedMeteringProfiles.map(\n (entry, index) => {\n const path =\n \"genericBodyMeteringCapabilityProfile.supportedMeteringProfiles[\" +\n index +\n \"]\";\n const item =\n requireRecord(entry, path, [\"meteringProfileId\", \"policyKind\", \"evidence\"]);\n return {\n meteringProfileId:\n requireNonEmptyString(\n item.meteringProfileId,\n path + \".meteringProfileId\"\n ),\n policyKind:\n parsePolicyKind(\n item.policyKind,\n path + \".policyKind\"\n ),\n evidence:\n parseEvidenceList(\n item.evidence,\n path + \".evidence\"\n )\n };\n }\n );\n\n const ids =\n supported.map(\n (entry) =>\n entry.meteringProfileId\n );\n if (\n new Set(ids).size !==\n ids.length\n ) {\n throw new InvalidConfigurationError(\n \"genericBodyMeteringCapabilityProfile.supportedMeteringProfiles must not contain duplicate meteringProfileId values.\"\n );\n }\n\n const spotLink =\n requireRecord(\n record.spotFocusPointLinkage,\n \"genericBodyMeteringCapabilityProfile.spotFocusPointLinkage\", [\"availability\", \"evidence\"]\n );\n\n return {\n schemaVersion:\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"genericBodyMeteringCapabilityProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"genericBodyMeteringCapabilityProfile.profileVersion\"\n ),\n scientificStatus:\n \"approximation\",\n evidence:\n parseEvidenceList(\n record.evidence,\n \"genericBodyMeteringCapabilityProfile.evidence\"\n ),\n supportedMeteringProfiles:\n supported,\n spotFocusPointLinkage: {\n availability:\n parseAvailability(\n spotLink.availability,\n \"genericBodyMeteringCapabilityProfile.spotFocusPointLinkage.availability\"\n ),\n evidence:\n parseEvidenceList(\n spotLink.evidence,\n \"genericBodyMeteringCapabilityProfile.spotFocusPointLinkage.evidence\"\n )\n }\n };\n}\n\n/**\n * Checks whether one engine metering profile is selectable on a generic body.\n *\n * The metering profile stays the single source of its calibration and target\n * policy. They are never copied into equipment capability metadata.\n */\nexport function assessExposureMeteringProfileCompatibility(\n input:\n AssessExposureMeteringProfileCompatibilityInput\n): MeteringCapabilityCompatibilityAssessment {\n requireInputKeys(input, \"assessExposureMeteringProfileCompatibility\", [\"bodyCapabilities\", \"meteringProfile\"]);\n const body =\n parseGenericBodyMeteringCapabilityProfile(\n input.bodyCapabilities\n );\n const metering =\n parseExposureMeteringProfile(\n input.meteringProfile\n );\n\n const declared =\n body.supportedMeteringProfiles.find(\n (entry) =>\n entry.meteringProfileId ===\n metering.profileId\n );\n\n const blockers:\n MeteringCapabilityCompatibilityBlocker[] =\n [];\n\n if (declared === undefined) {\n blockers.push(\n \"metering-profile-unsupported\"\n );\n } else if (\n declared.policyKind !==\n metering.policy.kind\n ) {\n blockers.push(\n \"metering-policy-mismatch\"\n );\n }\n\n if (\n blockers.length >\n new Set(blockers).size\n ) {\n throw new InvalidScientificInputError(\n \"Metering capability compatibility blockers must remain unique.\"\n );\n }\n\n return {\n schemaVersion:\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION,\n status:\n blockers.length === 0\n ? \"compatible\"\n : \"blocked\",\n bodyProfile: {\n profileId: body.profileId,\n profileVersion:\n body.profileVersion\n },\n meteringProfile: {\n profileId:\n metering.profileId,\n policyKind:\n metering.policy.kind\n },\n targetPolicyOwnership:\n \"metering-profile\",\n targetCalibrationDuplicatedInEquipmentProfile:\n false,\n spotFocusPointLinkageAvailability:\n body.spotFocusPointLinkage\n .availability,\n blockers\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"metering-capabilities.js","sourceRoot":"","sources":["../../src/equipment/metering-capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Metering capabilities of a generic body: which of the engine's metering profiles and modes it can\n * select.\n *\n * This profile deliberately does not copy target or calibration values from those metering profiles.\n * The metering profile stays the single source of its calibration and target policy.\n * @see docs/GENERIC_TIER_PRESETS.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport {\n parseExposureMeteringProfile,\n type ExposureMeteringPolicy,\n type ExposureMeteringProfile\n} from \"../exposure/metering.js\";\nimport type { GenericCapabilityAvailability } from \"./exposure-capabilities.js\";\nimport { requireInputKeys, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, parseConfigAvailability as parseAvailability } from \"../core/record-validation.js\";\n\n\nexport const GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION =\n \"0.1.0\" as const;\n\nexport interface GenericSupportedMeteringProfile {\n meteringProfileId: string;\n policyKind: ExposureMeteringPolicy[\"kind\"];\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface GenericBodyMeteringCapabilityProfile {\n schemaVersion:\n typeof GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n scientificStatus: \"approximation\";\n evidence: readonly EvidenceProvenance[];\n supportedMeteringProfiles:\n readonly GenericSupportedMeteringProfile[];\n spotFocusPointLinkage: {\n availability: GenericCapabilityAvailability;\n evidence: readonly EvidenceProvenance[];\n };\n}\n\nexport type MeteringCapabilityCompatibilityBlocker =\n | \"metering-profile-unsupported\"\n | \"metering-policy-mismatch\";\n\nexport interface MeteringCapabilityCompatibilityAssessment {\n schemaVersion:\n typeof GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION;\n status: \"compatible\" | \"blocked\";\n bodyProfile: {\n profileId: string;\n profileVersion: string;\n };\n meteringProfile: {\n profileId: string;\n policyKind: ExposureMeteringPolicy[\"kind\"];\n };\n targetPolicyOwnership: \"metering-profile\";\n targetCalibrationDuplicatedInEquipmentProfile: false;\n spotFocusPointLinkageAvailability:\n GenericCapabilityAvailability;\n blockers:\n readonly MeteringCapabilityCompatibilityBlocker[];\n}\n\nexport interface AssessExposureMeteringProfileCompatibilityInput {\n bodyCapabilities:\n GenericBodyMeteringCapabilityProfile;\n meteringProfile:\n ExposureMeteringProfile;\n}\n\nconst POLICY_KINDS =\n new Set<ExposureMeteringPolicy[\"kind\"]>([\n \"multi-zone-uniform\",\n \"center-weighted-radial\",\n \"spot\",\n \"highlight-weighted\",\n \"highlight-priority\"\n ]);\n\nfunction parsePolicyKind(\n value: unknown,\n path: string\n): ExposureMeteringPolicy[\"kind\"] {\n if (\n typeof value !== \"string\" ||\n !POLICY_KINDS.has(\n value as ExposureMeteringPolicy[\"kind\"]\n )\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value as ExposureMeteringPolicy[\"kind\"];\n}\n\n/**\n * Parses generic body metering capability metadata.\n *\n * This profile declares which of the engine's metering profiles and modes a\n * generic body can select. It deliberately does not copy target or\n * calibration values from those metering profiles.\n */\nexport function parseGenericBodyMeteringCapabilityProfile(\n value: unknown\n): GenericBodyMeteringCapabilityProfile {\n const record = requireRecord(\n value,\n \"genericBodyMeteringCapabilityProfile\", [\"schemaVersion\", \"scientificStatus\", \"supportedMeteringProfiles\", \"spotFocusPointLinkage\", \"profileId\", \"profileVersion\", \"evidence\"]\n );\n\n if (\n record.schemaVersion !==\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'genericBodyMeteringCapabilityProfile.schemaVersion must be \"' +\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION +\n '\".'\n );\n }\n if (\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n 'genericBodyMeteringCapabilityProfile.scientificStatus must be \"approximation\".'\n );\n }\n\n if (\n !Array.isArray(\n record.supportedMeteringProfiles\n ) ||\n record.supportedMeteringProfiles\n .length === 0\n ) {\n throw new InvalidConfigurationError(\n \"genericBodyMeteringCapabilityProfile.supportedMeteringProfiles must be a non-empty array.\"\n );\n }\n\n const supported =\n record.supportedMeteringProfiles.map(\n (entry, index) => {\n const path =\n \"genericBodyMeteringCapabilityProfile.supportedMeteringProfiles[\" +\n index +\n \"]\";\n const item =\n requireRecord(entry, path, [\"meteringProfileId\", \"policyKind\", \"evidence\"]);\n return {\n meteringProfileId:\n requireNonEmptyString(\n item.meteringProfileId,\n path + \".meteringProfileId\"\n ),\n policyKind:\n parsePolicyKind(\n item.policyKind,\n path + \".policyKind\"\n ),\n evidence:\n parseEvidenceList(\n item.evidence,\n path + \".evidence\"\n )\n };\n }\n );\n\n const ids =\n supported.map(\n (entry) =>\n entry.meteringProfileId\n );\n if (\n new Set(ids).size !==\n ids.length\n ) {\n throw new InvalidConfigurationError(\n \"genericBodyMeteringCapabilityProfile.supportedMeteringProfiles must not contain duplicate meteringProfileId values.\"\n );\n }\n\n const spotLink =\n requireRecord(\n record.spotFocusPointLinkage,\n \"genericBodyMeteringCapabilityProfile.spotFocusPointLinkage\", [\"availability\", \"evidence\"]\n );\n\n return {\n schemaVersion:\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"genericBodyMeteringCapabilityProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"genericBodyMeteringCapabilityProfile.profileVersion\"\n ),\n scientificStatus:\n \"approximation\",\n evidence:\n parseEvidenceList(\n record.evidence,\n \"genericBodyMeteringCapabilityProfile.evidence\"\n ),\n supportedMeteringProfiles:\n supported,\n spotFocusPointLinkage: {\n availability:\n parseAvailability(\n spotLink.availability,\n \"genericBodyMeteringCapabilityProfile.spotFocusPointLinkage.availability\"\n ),\n evidence:\n parseEvidenceList(\n spotLink.evidence,\n \"genericBodyMeteringCapabilityProfile.spotFocusPointLinkage.evidence\"\n )\n }\n };\n}\n\n/**\n * Checks whether one engine metering profile is selectable on a generic body.\n *\n * The metering profile stays the single source of its calibration and target\n * policy. They are never copied into equipment capability metadata.\n */\nexport function assessExposureMeteringProfileCompatibility(\n input:\n AssessExposureMeteringProfileCompatibilityInput\n): MeteringCapabilityCompatibilityAssessment {\n requireInputKeys(input, \"assessExposureMeteringProfileCompatibility\", [\"bodyCapabilities\", \"meteringProfile\"]);\n const body =\n parseGenericBodyMeteringCapabilityProfile(\n input.bodyCapabilities\n );\n const metering =\n parseExposureMeteringProfile(\n input.meteringProfile\n );\n\n const declared =\n body.supportedMeteringProfiles.find(\n (entry) =>\n entry.meteringProfileId ===\n metering.profileId\n );\n\n const blockers:\n MeteringCapabilityCompatibilityBlocker[] =\n [];\n\n if (declared === undefined) {\n blockers.push(\n \"metering-profile-unsupported\"\n );\n } else if (\n declared.policyKind !==\n metering.policy.kind\n ) {\n blockers.push(\n \"metering-policy-mismatch\"\n );\n }\n\n if (\n blockers.length >\n new Set(blockers).size\n ) {\n throw new InvalidScientificInputError(\n \"Metering capability compatibility blockers must remain unique.\"\n );\n }\n\n return {\n schemaVersion:\n GENERIC_BODY_METERING_CAPABILITY_SCHEMA_VERSION,\n status:\n blockers.length === 0\n ? \"compatible\"\n : \"blocked\",\n bodyProfile: {\n profileId: body.profileId,\n profileVersion:\n body.profileVersion\n },\n meteringProfile: {\n profileId:\n metering.profileId,\n policyKind:\n metering.policy.kind\n },\n targetPolicyOwnership:\n \"metering-profile\",\n targetCalibrationDuplicatedInEquipmentProfile:\n false,\n spotFocusPointLinkageAvailability:\n body.spotFocusPointLinkage\n .availability,\n blockers\n };\n}\n"]}
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
* @see docs/GENERIC_TIER_PRESETS.md for the equations, units, coordinate conventions, known blockers
|
|
9
9
|
* and support limits.
|
|
10
10
|
*/
|
|
11
|
-
import { rejectUnknownFields } from "../core/record-validation.js";
|
|
12
11
|
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
13
12
|
import { parseEvidenceList } from "../core/evidence-provenance.js";
|
|
13
|
+
import { requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, requireConfigPositiveFinite as requirePositiveFinite, requireConfigPositiveSafeInteger as requirePositiveSafeInteger, requireConfigNonNegativeFinite as requireNonNegativeFinite, parseConfigAvailability as parseAvailability } from "../core/record-validation.js";
|
|
14
14
|
export const GENERIC_RELEASE_CAPABILITY_SCHEMA_VERSION = "0.1.0";
|
|
15
15
|
const DRIVE_MODES = new Set([
|
|
16
16
|
"single",
|
|
@@ -22,58 +22,6 @@ const BRACKET_AXES = new Set([
|
|
|
22
22
|
"iso",
|
|
23
23
|
"aperture"
|
|
24
24
|
]);
|
|
25
|
-
function requireRecord(value, path, allowedKeys) {
|
|
26
|
-
if (typeof value !== "object" ||
|
|
27
|
-
value === null ||
|
|
28
|
-
Array.isArray(value)) {
|
|
29
|
-
throw new InvalidConfigurationError(path + " must be an object.");
|
|
30
|
-
}
|
|
31
|
-
if (allowedKeys !== null)
|
|
32
|
-
rejectUnknownFields(value, allowedKeys, path);
|
|
33
|
-
return value;
|
|
34
|
-
}
|
|
35
|
-
function requireNonEmptyString(value, path) {
|
|
36
|
-
if (typeof value !== "string" ||
|
|
37
|
-
value.trim().length === 0) {
|
|
38
|
-
throw new InvalidConfigurationError(path + " must be a non-empty string.");
|
|
39
|
-
}
|
|
40
|
-
return value.trim();
|
|
41
|
-
}
|
|
42
|
-
function requirePositiveFinite(value, path) {
|
|
43
|
-
if (typeof value !== "number" ||
|
|
44
|
-
!Number.isFinite(value) ||
|
|
45
|
-
value <= 0) {
|
|
46
|
-
throw new InvalidConfigurationError(path +
|
|
47
|
-
" must be finite and greater than zero.");
|
|
48
|
-
}
|
|
49
|
-
return value;
|
|
50
|
-
}
|
|
51
|
-
function requireNonNegativeFinite(value, path) {
|
|
52
|
-
if (typeof value !== "number" ||
|
|
53
|
-
!Number.isFinite(value) ||
|
|
54
|
-
value < 0) {
|
|
55
|
-
throw new InvalidConfigurationError(path +
|
|
56
|
-
" must be finite and greater than or equal to zero.");
|
|
57
|
-
}
|
|
58
|
-
return value;
|
|
59
|
-
}
|
|
60
|
-
function requirePositiveSafeInteger(value, path) {
|
|
61
|
-
if (typeof value !== "number" ||
|
|
62
|
-
!Number.isSafeInteger(value) ||
|
|
63
|
-
value <= 0) {
|
|
64
|
-
throw new InvalidConfigurationError(path +
|
|
65
|
-
" must be a positive safe integer.");
|
|
66
|
-
}
|
|
67
|
-
return value;
|
|
68
|
-
}
|
|
69
|
-
function parseAvailability(value, path) {
|
|
70
|
-
if (value !== "supported" &&
|
|
71
|
-
value !== "unsupported" &&
|
|
72
|
-
value !== "unknown") {
|
|
73
|
-
throw new InvalidConfigurationError(path + " is invalid.");
|
|
74
|
-
}
|
|
75
|
-
return value;
|
|
76
|
-
}
|
|
77
25
|
function parseFact(value, path, parseValue) {
|
|
78
26
|
const record = requireRecord(value, path, ["value", "evidence"]);
|
|
79
27
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release-capabilities.js","sourceRoot":"","sources":["../../src/equipment/release-capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Release and drive capabilities of a generic body: what happens when the shutter button is pressed\n * (single shot, burst, self-timer, and exposure brackets).\n *\n * The first schema deliberately models only ordinary still exposures that do not overlap. Slowdown\n * from the buffer, media or heat, and pre-release capture, are not part of this profile.\n * @see docs/GENERIC_TIER_PRESETS.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { rejectUnknownFields } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceBackedFact,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport type { GenericCapabilityAvailability } from \"./exposure-capabilities.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport const GENERIC_RELEASE_CAPABILITY_SCHEMA_VERSION =\n \"0.1.0\" as const;\n\nexport type GenericReleaseDriveMode =\n | \"single\"\n | \"burst\"\n | \"self-timer\";\n\nexport type GenericExposureBracketAxis =\n | \"shutter\"\n | \"iso\"\n | \"aperture\";\n\nexport interface GenericReleaseCapabilityProfile {\n schemaVersion:\n typeof GENERIC_RELEASE_CAPABILITY_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n scientificStatus: \"approximation\";\n evidence: readonly EvidenceProvenance[];\n supportedDriveModes:\n EvidenceBackedFact<\n readonly GenericReleaseDriveMode[]\n >;\n maximumLogicalFramesPerSequence:\n EvidenceBackedFact<number>;\n maximumCadenceFps:\n EvidenceBackedFact<number>;\n minimumInterFrameGapSeconds:\n EvidenceBackedFact<number>;\n overlappingOrdinaryStillExposures:\n false;\n exposureBracketing: {\n availability:\n EvidenceBackedFact<\n GenericCapabilityAvailability\n >;\n supportedAxes:\n readonly GenericExposureBracketAxis[];\n };\n focusBracketing: {\n availability:\n EvidenceBackedFact<\n GenericCapabilityAvailability\n >;\n };\n}\n\nconst DRIVE_MODES =\n new Set<GenericReleaseDriveMode>([\n \"single\",\n \"burst\",\n \"self-timer\"\n ]);\n\nconst BRACKET_AXES =\n new Set<GenericExposureBracketAxis>([\n \"shutter\",\n \"iso\",\n \"aperture\"\n ]);\n\nfunction requireRecord(\n value: unknown,\n path: string,\n allowedKeys: readonly string[] | null\n): UnknownRecord {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be an object.\"\n );\n }\n if (allowedKeys !== null) rejectUnknownFields(value, allowedKeys, path);\n return value as UnknownRecord;\n}\n\nfunction requireNonEmptyString(\n value: unknown,\n path: string\n): string {\n if (\n typeof value !== \"string\" ||\n value.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n path + \" must be a non-empty string.\"\n );\n }\n return value.trim();\n}\n\nfunction requirePositiveFinite(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n value <= 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must be finite and greater than zero.\"\n );\n }\n return value;\n}\n\nfunction requireNonNegativeFinite(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n value < 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must be finite and greater than or equal to zero.\"\n );\n }\n return value;\n}\n\nfunction requirePositiveSafeInteger(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isSafeInteger(value) ||\n value <= 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must be a positive safe integer.\"\n );\n }\n return value;\n}\n\nfunction parseAvailability(\n value: unknown,\n path: string\n): GenericCapabilityAvailability {\n if (\n value !== \"supported\" &&\n value !== \"unsupported\" &&\n value !== \"unknown\"\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value;\n}\n\nfunction parseFact<T>(\n value: unknown,\n path: string,\n parseValue: (\n value: unknown,\n path: string\n ) => T\n): EvidenceBackedFact<T> {\n const record =\n requireRecord(value, path, [\"value\", \"evidence\"]);\n return {\n value:\n parseValue(\n record.value,\n path + \".value\"\n ),\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\nfunction parseDriveModes(\n value: unknown,\n path: string\n): readonly GenericReleaseDriveMode[] {\n if (\n !Array.isArray(value) ||\n value.length === 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must be a non-empty array.\"\n );\n }\n const parsed =\n value.map((entry, index) => {\n if (\n typeof entry !== \"string\" ||\n !DRIVE_MODES.has(\n entry as GenericReleaseDriveMode\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \"[\" +\n index +\n \"] is invalid.\"\n );\n }\n return entry as GenericReleaseDriveMode;\n });\n if (\n new Set(parsed).size !==\n parsed.length\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must not contain duplicates.\"\n );\n }\n return parsed;\n}\n\nfunction parseBracketAxes(\n value: unknown,\n path: string\n): readonly GenericExposureBracketAxis[] {\n if (!Array.isArray(value)) {\n throw new InvalidConfigurationError(\n path + \" must be an array.\"\n );\n }\n const parsed =\n value.map((entry, index) => {\n if (\n typeof entry !== \"string\" ||\n !BRACKET_AXES.has(\n entry as GenericExposureBracketAxis\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \"[\" +\n index +\n \"] is invalid.\"\n );\n }\n return entry as GenericExposureBracketAxis;\n });\n if (\n new Set(parsed).size !==\n parsed.length\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must not contain duplicates.\"\n );\n }\n return parsed;\n}\n\n/**\n * Parses generic logical-release/drive capabilities.\n *\n * The first schema deliberately models only ordinary still exposures that do\n * not overlap. Slowdown from the buffer, media or heat, and pre-release\n * capture, are not part of this profile.\n */\nexport function parseGenericReleaseCapabilityProfile(\n value: unknown\n): GenericReleaseCapabilityProfile {\n const record =\n requireRecord(\n value,\n \"genericReleaseCapabilityProfile\", [\"schemaVersion\", \"scientificStatus\", \"overlappingOrdinaryStillExposures\", \"exposureBracketing\", \"focusBracketing\", \"profileId\", \"profileVersion\", \"evidence\", \"supportedDriveModes\", \"maximumLogicalFramesPerSequence\", \"maximumCadenceFps\", \"minimumInterFrameGapSeconds\"]\n );\n\n if (\n record.schemaVersion !==\n GENERIC_RELEASE_CAPABILITY_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'genericReleaseCapabilityProfile.schemaVersion must be \"' +\n GENERIC_RELEASE_CAPABILITY_SCHEMA_VERSION +\n '\".'\n );\n }\n if (\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n 'genericReleaseCapabilityProfile.scientificStatus must be \"approximation\".'\n );\n }\n if (\n record.overlappingOrdinaryStillExposures !==\n false\n ) {\n throw new InvalidConfigurationError(\n \"genericReleaseCapabilityProfile.overlappingOrdinaryStillExposures must be false in schema 0.1.0.\"\n );\n }\n\n const exposureBracketing =\n requireRecord(\n record.exposureBracketing,\n \"genericReleaseCapabilityProfile.exposureBracketing\", [\"availability\", \"supportedAxes\"]\n );\n const focusBracketing =\n requireRecord(\n record.focusBracketing,\n \"genericReleaseCapabilityProfile.focusBracketing\", [\"availability\"]\n );\n\n const exposureAvailability =\n parseFact(\n exposureBracketing.availability,\n \"genericReleaseCapabilityProfile.exposureBracketing.availability\",\n parseAvailability\n );\n const axes =\n parseBracketAxes(\n exposureBracketing.supportedAxes,\n \"genericReleaseCapabilityProfile.exposureBracketing.supportedAxes\"\n );\n\n if (\n exposureAvailability.value !==\n \"supported\" &&\n axes.length > 0\n ) {\n throw new InvalidConfigurationError(\n \"Unsupported/unknown exposure bracketing must not declare supported axes.\"\n );\n }\n\n return {\n schemaVersion:\n GENERIC_RELEASE_CAPABILITY_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"genericReleaseCapabilityProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"genericReleaseCapabilityProfile.profileVersion\"\n ),\n scientificStatus:\n \"approximation\",\n evidence:\n parseEvidenceList(\n record.evidence,\n \"genericReleaseCapabilityProfile.evidence\"\n ),\n supportedDriveModes:\n parseFact(\n record.supportedDriveModes,\n \"genericReleaseCapabilityProfile.supportedDriveModes\",\n parseDriveModes\n ),\n maximumLogicalFramesPerSequence:\n parseFact(\n record.maximumLogicalFramesPerSequence,\n \"genericReleaseCapabilityProfile.maximumLogicalFramesPerSequence\",\n requirePositiveSafeInteger\n ),\n maximumCadenceFps:\n parseFact(\n record.maximumCadenceFps,\n \"genericReleaseCapabilityProfile.maximumCadenceFps\",\n requirePositiveFinite\n ),\n minimumInterFrameGapSeconds:\n parseFact(\n record.minimumInterFrameGapSeconds,\n \"genericReleaseCapabilityProfile.minimumInterFrameGapSeconds\",\n requireNonNegativeFinite\n ),\n overlappingOrdinaryStillExposures:\n false,\n exposureBracketing: {\n availability:\n exposureAvailability,\n supportedAxes: axes\n },\n focusBracketing: {\n availability:\n parseFact(\n focusBracketing.availability,\n \"genericReleaseCapabilityProfile.focusBracketing.availability\",\n parseAvailability\n )\n }\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"release-capabilities.js","sourceRoot":"","sources":["../../src/equipment/release-capabilities.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Release and drive capabilities of a generic body: what happens when the shutter button is pressed\n * (single shot, burst, self-timer, and exposure brackets).\n *\n * The first schema deliberately models only ordinary still exposures that do not overlap. Slowdown\n * from the buffer, media or heat, and pre-release capture, are not part of this profile.\n * @see docs/GENERIC_TIER_PRESETS.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceBackedFact,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport type { GenericCapabilityAvailability } from \"./exposure-capabilities.js\";\nimport { requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, requireConfigPositiveFinite as requirePositiveFinite, requireConfigPositiveSafeInteger as requirePositiveSafeInteger, requireConfigNonNegativeFinite as requireNonNegativeFinite, parseConfigAvailability as parseAvailability } from \"../core/record-validation.js\";\n\n\nexport const GENERIC_RELEASE_CAPABILITY_SCHEMA_VERSION =\n \"0.1.0\" as const;\n\nexport type GenericReleaseDriveMode =\n | \"single\"\n | \"burst\"\n | \"self-timer\";\n\nexport type GenericExposureBracketAxis =\n | \"shutter\"\n | \"iso\"\n | \"aperture\";\n\nexport interface GenericReleaseCapabilityProfile {\n schemaVersion:\n typeof GENERIC_RELEASE_CAPABILITY_SCHEMA_VERSION;\n profileId: string;\n profileVersion: string;\n scientificStatus: \"approximation\";\n evidence: readonly EvidenceProvenance[];\n supportedDriveModes:\n EvidenceBackedFact<\n readonly GenericReleaseDriveMode[]\n >;\n maximumLogicalFramesPerSequence:\n EvidenceBackedFact<number>;\n maximumCadenceFps:\n EvidenceBackedFact<number>;\n minimumInterFrameGapSeconds:\n EvidenceBackedFact<number>;\n overlappingOrdinaryStillExposures:\n false;\n exposureBracketing: {\n availability:\n EvidenceBackedFact<\n GenericCapabilityAvailability\n >;\n supportedAxes:\n readonly GenericExposureBracketAxis[];\n };\n focusBracketing: {\n availability:\n EvidenceBackedFact<\n GenericCapabilityAvailability\n >;\n };\n}\n\nconst DRIVE_MODES =\n new Set<GenericReleaseDriveMode>([\n \"single\",\n \"burst\",\n \"self-timer\"\n ]);\n\nconst BRACKET_AXES =\n new Set<GenericExposureBracketAxis>([\n \"shutter\",\n \"iso\",\n \"aperture\"\n ]);\n\nfunction parseFact<T>(\n value: unknown,\n path: string,\n parseValue: (\n value: unknown,\n path: string\n ) => T\n): EvidenceBackedFact<T> {\n const record =\n requireRecord(value, path, [\"value\", \"evidence\"]);\n return {\n value:\n parseValue(\n record.value,\n path + \".value\"\n ),\n evidence:\n parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\nfunction parseDriveModes(\n value: unknown,\n path: string\n): readonly GenericReleaseDriveMode[] {\n if (\n !Array.isArray(value) ||\n value.length === 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must be a non-empty array.\"\n );\n }\n const parsed =\n value.map((entry, index) => {\n if (\n typeof entry !== \"string\" ||\n !DRIVE_MODES.has(\n entry as GenericReleaseDriveMode\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \"[\" +\n index +\n \"] is invalid.\"\n );\n }\n return entry as GenericReleaseDriveMode;\n });\n if (\n new Set(parsed).size !==\n parsed.length\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must not contain duplicates.\"\n );\n }\n return parsed;\n}\n\nfunction parseBracketAxes(\n value: unknown,\n path: string\n): readonly GenericExposureBracketAxis[] {\n if (!Array.isArray(value)) {\n throw new InvalidConfigurationError(\n path + \" must be an array.\"\n );\n }\n const parsed =\n value.map((entry, index) => {\n if (\n typeof entry !== \"string\" ||\n !BRACKET_AXES.has(\n entry as GenericExposureBracketAxis\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \"[\" +\n index +\n \"] is invalid.\"\n );\n }\n return entry as GenericExposureBracketAxis;\n });\n if (\n new Set(parsed).size !==\n parsed.length\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must not contain duplicates.\"\n );\n }\n return parsed;\n}\n\n/**\n * Parses generic logical-release/drive capabilities.\n *\n * The first schema deliberately models only ordinary still exposures that do\n * not overlap. Slowdown from the buffer, media or heat, and pre-release\n * capture, are not part of this profile.\n */\nexport function parseGenericReleaseCapabilityProfile(\n value: unknown\n): GenericReleaseCapabilityProfile {\n const record =\n requireRecord(\n value,\n \"genericReleaseCapabilityProfile\", [\"schemaVersion\", \"scientificStatus\", \"overlappingOrdinaryStillExposures\", \"exposureBracketing\", \"focusBracketing\", \"profileId\", \"profileVersion\", \"evidence\", \"supportedDriveModes\", \"maximumLogicalFramesPerSequence\", \"maximumCadenceFps\", \"minimumInterFrameGapSeconds\"]\n );\n\n if (\n record.schemaVersion !==\n GENERIC_RELEASE_CAPABILITY_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'genericReleaseCapabilityProfile.schemaVersion must be \"' +\n GENERIC_RELEASE_CAPABILITY_SCHEMA_VERSION +\n '\".'\n );\n }\n if (\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n 'genericReleaseCapabilityProfile.scientificStatus must be \"approximation\".'\n );\n }\n if (\n record.overlappingOrdinaryStillExposures !==\n false\n ) {\n throw new InvalidConfigurationError(\n \"genericReleaseCapabilityProfile.overlappingOrdinaryStillExposures must be false in schema 0.1.0.\"\n );\n }\n\n const exposureBracketing =\n requireRecord(\n record.exposureBracketing,\n \"genericReleaseCapabilityProfile.exposureBracketing\", [\"availability\", \"supportedAxes\"]\n );\n const focusBracketing =\n requireRecord(\n record.focusBracketing,\n \"genericReleaseCapabilityProfile.focusBracketing\", [\"availability\"]\n );\n\n const exposureAvailability =\n parseFact(\n exposureBracketing.availability,\n \"genericReleaseCapabilityProfile.exposureBracketing.availability\",\n parseAvailability\n );\n const axes =\n parseBracketAxes(\n exposureBracketing.supportedAxes,\n \"genericReleaseCapabilityProfile.exposureBracketing.supportedAxes\"\n );\n\n if (\n exposureAvailability.value !==\n \"supported\" &&\n axes.length > 0\n ) {\n throw new InvalidConfigurationError(\n \"Unsupported/unknown exposure bracketing must not declare supported axes.\"\n );\n }\n\n return {\n schemaVersion:\n GENERIC_RELEASE_CAPABILITY_SCHEMA_VERSION,\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"genericReleaseCapabilityProfile.profileId\"\n ),\n profileVersion:\n requireNonEmptyString(\n record.profileVersion,\n \"genericReleaseCapabilityProfile.profileVersion\"\n ),\n scientificStatus:\n \"approximation\",\n evidence:\n parseEvidenceList(\n record.evidence,\n \"genericReleaseCapabilityProfile.evidence\"\n ),\n supportedDriveModes:\n parseFact(\n record.supportedDriveModes,\n \"genericReleaseCapabilityProfile.supportedDriveModes\",\n parseDriveModes\n ),\n maximumLogicalFramesPerSequence:\n parseFact(\n record.maximumLogicalFramesPerSequence,\n \"genericReleaseCapabilityProfile.maximumLogicalFramesPerSequence\",\n requirePositiveSafeInteger\n ),\n maximumCadenceFps:\n parseFact(\n record.maximumCadenceFps,\n \"genericReleaseCapabilityProfile.maximumCadenceFps\",\n requirePositiveFinite\n ),\n minimumInterFrameGapSeconds:\n parseFact(\n record.minimumInterFrameGapSeconds,\n \"genericReleaseCapabilityProfile.minimumInterFrameGapSeconds\",\n requireNonNegativeFinite\n ),\n overlappingOrdinaryStillExposures:\n false,\n exposureBracketing: {\n availability:\n exposureAvailability,\n supportedAxes: axes\n },\n focusBracketing: {\n availability:\n parseFact(\n focusBracketing.availability,\n \"genericReleaseCapabilityProfile.focusBracketing.availability\",\n parseAvailability\n )\n }\n };\n}\n"]}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import { approximationResult } from "../core/calculation-result.js";
|
|
22
22
|
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
23
|
-
import { rejectUnknownFields, requireInputKeys, requireInputObject } from "../core/record-validation.js";
|
|
23
|
+
import { rejectUnknownFields, requireInputKeys, requireInputObject, requireInputPositiveFinite as requirePositive } from "../core/record-validation.js";
|
|
24
24
|
import { InvalidScientificInputError, InvalidScientificResultError } from "../core/validation.js";
|
|
25
25
|
import { portableHypot } from "../core/portable-math.js";
|
|
26
26
|
import { estimateCameraShakeBlur } from "../stabilization/camera-shake.js";
|
|
@@ -40,12 +40,6 @@ export const GENERIC_HANDHELD_ANGULAR_VELOCITY_RAD_PER_SEC =
|
|
|
40
40
|
/* @__PURE__ */ Object.freeze({ yaw: (4.39 * Math.PI) / 180, pitch: 0 });
|
|
41
41
|
/** The largest whole-stop bias accepted, either way (makers offer up to 2 stops faster or slower). */
|
|
42
42
|
export const AUTO_ISO_SLOWEST_SHUTTER_MAXIMUM_BIAS_STOPS = 2;
|
|
43
|
-
function requirePositive(value, path) {
|
|
44
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
45
|
-
throw new InvalidScientificInputError(path + " must be finite and greater than zero.");
|
|
46
|
-
}
|
|
47
|
-
return value;
|
|
48
|
-
}
|
|
49
43
|
function parseBudget(value) {
|
|
50
44
|
requireInputObject(value, "blurBudget");
|
|
51
45
|
const record = value;
|