@photivra/engine 2.17.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 +116 -1
- package/CITATION.cff +1 -1
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/dist/camera/sensor-equivalence.d.ts +156 -0
- package/dist/camera/sensor-equivalence.js +208 -0
- package/dist/camera/sensor-equivalence.js.map +1 -0
- 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/native-environment-tabulated.d.ts +5 -0
- package/dist/capture/native-environment-tabulated.js +1 -1
- package/dist/capture/native-environment-tabulated.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/ideal-lens.d.ts +25 -0
- package/dist/equipment/ideal-lens.js +21 -0
- package/dist/equipment/ideal-lens.js.map +1 -0
- 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/catalogue-lens-signal.d.ts +94 -0
- package/dist/facade/catalogue-lens-signal.js +362 -0
- package/dist/facade/catalogue-lens-signal.js.map +1 -0
- package/dist/facade/defocus-image-space-provider.js +5 -2
- package/dist/facade/defocus-image-space-provider.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/display-view-lens-signal.d.ts +32 -1
- package/dist/facade/display-view-lens-signal.js +85 -10
- package/dist/facade/display-view-lens-signal.js.map +1 -1
- package/dist/facade/expected-signal-setup.d.ts +8 -0
- package/dist/facade/expected-signal-setup.js +7 -0
- package/dist/facade/expected-signal-setup.js.map +1 -1
- package/dist/facade/expected-signal.d.ts +5 -0
- package/dist/facade/expected-signal.js +5 -1
- package/dist/facade/expected-signal.js.map +1 -1
- package/dist/facade/generic-lens-capture.d.ts +5 -2
- package/dist/facade/generic-lens-capture.js +5 -2
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +67 -8
- package/dist/facade/simulate-capture.js +262 -126
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.js +1 -1
- package/dist/facade/simulate-display-view.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 +6 -1
- package/dist/index.js +5 -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 +4 -0
- package/docs/API_REFERENCE.md +69 -2
- package/docs/QUICK_START.md +136 -6
- package/docs/USAGE.md +89 -3
- package/docs/api/camera-sensor-equivalence.md +209 -0
- package/docs/api/core-version.md +1 -1
- package/docs/api/equipment-ideal-lens.md +26 -0
- package/docs/api/exports.json +118 -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 +62 -8
- 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 +3 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"radiometry-readiness.js","sourceRoot":"","sources":["../../src/sensor/radiometry-readiness.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Radiometry readiness: checks whether the declared prerequisites are enough for a nominal photon\n * estimate and, separately, for a calibrated photon claim.\n *\n * The parser checks structure and provenance. It cannot prove that a cited calibration or evidence\n * claim is true. Passing this check does not switch on composed photon or noise output.\n * @see docs/MOTION_AND_SIGNAL.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport { rejectUnknownFields, rejectUnknownVariantFields, UNCERTAINTY_VARIANT_FIELDS } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport type RadiometryRequirementId =\n | \"scene-spectral-radiance\"\n | \"optical-transmission\"\n | \"pupil-vignetting\"\n | \"photosite-collection-area\"\n | \"exposure-integration\"\n | \"sensor-response\";\n\nexport type RadiometryScientificStatus =\n | \"calibrated\"\n | \"approximation\";\n\nexport type RadiometryUncertaintyDeclaration =\n | {\n kind: \"relative\";\n fraction: number;\n basis: string;\n }\n | {\n kind: \"absolute\";\n plusMinus: number;\n unit: string;\n basis: string;\n }\n | {\n kind: \"not-quantified\";\n limitation: string;\n };\n\nexport interface CalibrationArtifactReference {\n id: string;\n checksumSha256: string;\n}\n\ninterface RadiometryRequirementBase {\n requirement: RadiometryRequirementId;\n scientificStatus: RadiometryScientificStatus;\n modelId: string;\n modelVersion: string;\n evidence: readonly EvidenceProvenance[];\n uncertainty: RadiometryUncertaintyDeclaration;\n}\n\nexport interface SceneSpectralRadianceRequirement\n extends RadiometryRequirementBase {\n requirement: \"scene-spectral-radiance\";\n representation:\n | \"spectral-data\"\n | \"documented-spectral-approximation\";\n dataArtifact: CalibrationArtifactReference;\n}\n\nexport type OpticalTransmissionRequirement =\n | (RadiometryRequirementBase & {\n requirement: \"optical-transmission\";\n representation: \"spectral-data\";\n dataArtifact: CalibrationArtifactReference;\n })\n | (RadiometryRequirementBase & {\n requirement: \"optical-transmission\";\n representation: \"t-stop-approximation\";\n tStop: number;\n });\n\nexport type PupilVignettingRequirement =\n | (RadiometryRequirementBase & {\n requirement: \"pupil-vignetting\";\n representation: \"spatial-data\";\n dataArtifact: CalibrationArtifactReference;\n })\n | (RadiometryRequirementBase & {\n requirement: \"pupil-vignetting\";\n representation: \"documented-approximation\";\n });\n\nexport type PhotositeCollectionAreaRequirement =\n | (RadiometryRequirementBase & {\n requirement: \"photosite-collection-area\";\n areaModel: \"effective-collection-area\";\n effectiveCollectionAreaSquareMicrometers: number;\n })\n | (RadiometryRequirementBase & {\n requirement: \"photosite-collection-area\";\n areaModel: \"geometric-area-times-fill-factor\";\n geometricCellAreaSquareMicrometers: number;\n fillFactor: number;\n });\n\nexport type ExposureIntegrationRequirement =\n | (RadiometryRequirementBase & {\n requirement: \"exposure-integration\";\n integrationModel: \"uniform-boxcar\";\n })\n | (RadiometryRequirementBase & {\n requirement: \"exposure-integration\";\n integrationModel: \"documented-shutter-function\";\n dataArtifact: CalibrationArtifactReference;\n });\n\nexport type SensorResponseRequirement =\n | (RadiometryRequirementBase & {\n requirement: \"sensor-response\";\n responseRepresentation: \"spectral-quantum-efficiency\";\n dataArtifact: CalibrationArtifactReference;\n })\n | (RadiometryRequirementBase & {\n requirement: \"sensor-response\";\n responseRepresentation: \"effective-qe-approximation\";\n effectiveQuantumEfficiency: number;\n });\n\nexport type RadiometryRequirement =\n | SceneSpectralRadianceRequirement\n | OpticalTransmissionRequirement\n | PupilVignettingRequirement\n | PhotositeCollectionAreaRequirement\n | ExposureIntegrationRequirement\n | SensorResponseRequirement;\n\nexport interface RadiometryReadinessProfile {\n schemaVersion: \"0.1.0\";\n components: readonly RadiometryRequirement[];\n}\n\nexport interface RadiometryReadinessAssessment {\n status: \"not-ready\" | \"approximate-only\" | \"calibrated-ready\";\n nominalPhotonEstimateReady: boolean;\n calibratedPhotonClaimReady: boolean;\n missingRequirements: readonly RadiometryRequirementId[];\n approximateRequirements: readonly RadiometryRequirementId[];\n unquantifiedUncertaintyRequirements: readonly RadiometryRequirementId[];\n /**\n * Always false: this assessment never switches on composed photon or noise\n * output by itself. Doing so is a separate, explicit later decision.\n */\n composedPhotonOutputEnabled: false;\n}\n\nconst REQUIRED_REQUIREMENTS: readonly RadiometryRequirementId[] = [\n \"scene-spectral-radiance\",\n \"optical-transmission\",\n \"pupil-vignetting\",\n \"photosite-collection-area\",\n \"exposure-integration\",\n \"sensor-response\"\n];\n\nconst REQUIREMENT_IDS = new Set<RadiometryRequirementId>(\n REQUIRED_REQUIREMENTS\n);\n\nconst SCIENTIFIC_STATUSES = new Set<RadiometryScientificStatus>([\n \"calibrated\",\n \"approximation\"\n]);\n\nfunction requireRecord(\n value: unknown,\n path: string,\n allowedKeys: readonly string[] | null\n): UnknownRecord {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new InvalidConfigurationError(`${path} must be an object.`);\n }\n if (allowedKeys !== null) rejectUnknownFields(value, allowedKeys, path);\n return value as UnknownRecord;\n}\n\nfunction requireString(\n record: UnknownRecord,\n key: string,\n path: string\n): string {\n const value = record[key];\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new InvalidConfigurationError(\n `${path}.${key} must be a non-empty string.`\n );\n }\n return value;\n}\n\nfunction requirePositiveNumber(\n record: UnknownRecord,\n key: string,\n path: string\n): number {\n const value = record[key];\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n throw new InvalidConfigurationError(\n `${path}.${key} must be a finite number greater than zero.`\n );\n }\n return value;\n}\n\nfunction requireFraction(\n record: UnknownRecord,\n key: string,\n path: string,\n allowZero: boolean\n): number {\n const value = record[key];\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n (allowZero ? value < 0 : value <= 0) ||\n value > 1\n ) {\n throw new InvalidConfigurationError(\n `${path}.${key} must be a finite fraction ${allowZero ? \"from 0 through 1\" : \"greater than 0 and at most 1\"}.`\n );\n }\n return value;\n}\n\nfunction parseArtifact(\n value: unknown,\n path: string\n): CalibrationArtifactReference {\n const record = requireRecord(value, path, [\"id\", \"checksumSha256\"]);\n const id = requireString(record, \"id\", path);\n const checksumSha256 = requireString(\n record,\n \"checksumSha256\",\n path\n );\n if (!/^[a-f0-9]{64}$/iu.test(checksumSha256)) {\n throw new InvalidConfigurationError(\n `${path}.checksumSha256 must be a 64-character SHA-256 hex digest.`\n );\n }\n return { id, checksumSha256: checksumSha256.toLowerCase() };\n}\n\nfunction parseUncertainty(\n value: unknown,\n path: string\n): RadiometryUncertaintyDeclaration {\n const record = requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", { ...UNCERTAINTY_VARIANT_FIELDS, absolute: [\"kind\", \"plusMinus\", \"unit\", \"basis\"] }, path);\n const kind = requireString(record, \"kind\", path);\n\n if (kind === \"relative\") {\n const fraction = record.fraction;\n if (\n typeof fraction !== \"number\" ||\n !Number.isFinite(fraction) ||\n fraction < 0\n ) {\n throw new InvalidConfigurationError(\n `${path}.fraction must be finite and greater than or equal to zero.`\n );\n }\n return {\n kind,\n fraction,\n basis: requireString(record, \"basis\", path)\n };\n }\n\n if (kind === \"absolute\") {\n const plusMinus = record.plusMinus;\n if (\n typeof plusMinus !== \"number\" ||\n !Number.isFinite(plusMinus) ||\n plusMinus < 0\n ) {\n throw new InvalidConfigurationError(\n `${path}.plusMinus must be finite and greater than or equal to zero.`\n );\n }\n return {\n kind,\n plusMinus,\n unit: requireString(record, \"unit\", path),\n basis: requireString(record, \"basis\", path)\n };\n }\n\n if (kind === \"not-quantified\") {\n return {\n kind,\n limitation: requireString(record, \"limitation\", path)\n };\n }\n\n throw new InvalidConfigurationError(`${path}.kind is invalid.`);\n}\n\nfunction parseBase(\n record: UnknownRecord,\n path: string\n): Omit<RadiometryRequirementBase, \"requirement\"> {\n const scientificStatus = requireString(\n record,\n \"scientificStatus\",\n path\n );\n if (\n !SCIENTIFIC_STATUSES.has(\n scientificStatus as RadiometryScientificStatus\n )\n ) {\n throw new InvalidConfigurationError(\n `${path}.scientificStatus is invalid.`\n );\n }\n\n return {\n scientificStatus:\n scientificStatus as RadiometryScientificStatus,\n modelId: requireString(record, \"modelId\", path),\n modelVersion: requireString(record, \"modelVersion\", path),\n evidence: parseEvidenceList(record.evidence, `${path}.evidence`),\n uncertainty: parseUncertainty(\n record.uncertainty,\n `${path}.uncertainty`\n )\n };\n}\n\nfunction requireApproximationStatus(\n base: Omit<RadiometryRequirementBase, \"requirement\">,\n path: string,\n representation: string\n): void {\n if (base.scientificStatus !== \"approximation\") {\n throw new InvalidConfigurationError(\n `${path} uses inherently approximate representation \"${representation}\" and must declare scientificStatus \"approximation\".`\n );\n }\n}\n\nfunction parseRequirement(\n value: unknown,\n path: string\n): RadiometryRequirement {\n const record = requireRecord(value, path, [\"requirement\", \"scientificStatus\", \"modelId\", \"modelVersion\", \"evidence\", \"uncertainty\", \"representation\", \"dataArtifact\", \"tStop\", \"areaModel\", \"geometricPitchXMicrometers\", \"geometricPitchYMicrometers\", \"effectiveCollectionAreaSquareMicrometers\", \"geometricCellAreaSquareMicrometers\", \"fillFactor\", \"integrationModel\", \"responseRepresentation\", \"effectiveQuantumEfficiency\"]);\n const requirement = requireString(record, \"requirement\", path);\n if (!REQUIREMENT_IDS.has(requirement as RadiometryRequirementId)) {\n throw new InvalidConfigurationError(\n `${path}.requirement is invalid.`\n );\n }\n\n const base = parseBase(record, path);\n\n if (requirement === \"scene-spectral-radiance\") {\n const representation = requireString(\n record,\n \"representation\",\n path\n );\n if (\n representation !== \"spectral-data\" &&\n representation !== \"documented-spectral-approximation\"\n ) {\n throw new InvalidConfigurationError(\n `${path}.representation is invalid.`\n );\n }\n if (representation === \"documented-spectral-approximation\") {\n requireApproximationStatus(base, path, representation);\n }\n return {\n requirement,\n ...base,\n representation,\n dataArtifact: parseArtifact(\n record.dataArtifact,\n `${path}.dataArtifact`\n )\n };\n }\n\n if (requirement === \"optical-transmission\") {\n const representation = requireString(\n record,\n \"representation\",\n path\n );\n if (representation === \"spectral-data\") {\n return {\n requirement,\n ...base,\n representation,\n dataArtifact: parseArtifact(\n record.dataArtifact,\n `${path}.dataArtifact`\n )\n };\n }\n if (representation === \"t-stop-approximation\") {\n requireApproximationStatus(base, path, representation);\n return {\n requirement,\n ...base,\n representation,\n tStop: requirePositiveNumber(record, \"tStop\", path)\n };\n }\n throw new InvalidConfigurationError(\n `${path}.representation is invalid.`\n );\n }\n\n if (requirement === \"pupil-vignetting\") {\n const representation = requireString(\n record,\n \"representation\",\n path\n );\n if (representation === \"spatial-data\") {\n return {\n requirement,\n ...base,\n representation,\n dataArtifact: parseArtifact(\n record.dataArtifact,\n `${path}.dataArtifact`\n )\n };\n }\n if (representation === \"documented-approximation\") {\n requireApproximationStatus(base, path, representation);\n return { requirement, ...base, representation };\n }\n throw new InvalidConfigurationError(\n `${path}.representation is invalid.`\n );\n }\n\n if (requirement === \"photosite-collection-area\") {\n if (\n record.areaModel === undefined &&\n (record.geometricPitchXMicrometers !== undefined ||\n record.geometricPitchYMicrometers !== undefined)\n ) {\n throw new InvalidConfigurationError(\n `${path}.areaModel is required. Geometric sample pitch alone is not a photosite collection-area model.`\n );\n }\n const areaModel = requireString(record, \"areaModel\", path);\n if (areaModel === \"effective-collection-area\") {\n return {\n requirement,\n ...base,\n areaModel,\n effectiveCollectionAreaSquareMicrometers:\n requirePositiveNumber(\n record,\n \"effectiveCollectionAreaSquareMicrometers\",\n path\n )\n };\n }\n if (areaModel === \"geometric-area-times-fill-factor\") {\n return {\n requirement,\n ...base,\n areaModel,\n geometricCellAreaSquareMicrometers:\n requirePositiveNumber(\n record,\n \"geometricCellAreaSquareMicrometers\",\n path\n ),\n fillFactor: requireFraction(\n record,\n \"fillFactor\",\n path,\n false\n )\n };\n }\n throw new InvalidConfigurationError(\n `${path}.areaModel is invalid. Geometric sample pitch alone is not a photosite collection-area model.`\n );\n }\n\n if (requirement === \"exposure-integration\") {\n const integrationModel = requireString(\n record,\n \"integrationModel\",\n path\n );\n if (integrationModel === \"uniform-boxcar\") {\n return { requirement, ...base, integrationModel };\n }\n if (integrationModel === \"documented-shutter-function\") {\n return {\n requirement,\n ...base,\n integrationModel,\n dataArtifact: parseArtifact(\n record.dataArtifact,\n `${path}.dataArtifact`\n )\n };\n }\n throw new InvalidConfigurationError(\n `${path}.integrationModel is invalid.`\n );\n }\n\n const responseRepresentation = requireString(\n record,\n \"responseRepresentation\",\n path\n );\n if (responseRepresentation === \"spectral-quantum-efficiency\") {\n return {\n requirement: \"sensor-response\",\n ...base,\n responseRepresentation,\n dataArtifact: parseArtifact(\n record.dataArtifact,\n `${path}.dataArtifact`\n )\n };\n }\n if (responseRepresentation === \"effective-qe-approximation\") {\n requireApproximationStatus(base, path, responseRepresentation);\n return {\n requirement: \"sensor-response\",\n ...base,\n responseRepresentation,\n effectiveQuantumEfficiency: requireFraction(\n record,\n \"effectiveQuantumEfficiency\",\n path,\n true\n )\n };\n }\n throw new InvalidConfigurationError(\n `${path}.responseRepresentation is invalid.`\n );\n}\n\n/**\n * Parses untrusted metadata about radiometry prerequisites.\n *\n * It checks structure and provenance. It cannot prove that a cited calibration\n * or evidence claim is scientifically true.\n */\nexport function parseRadiometryReadinessProfile(\n value: unknown\n): RadiometryReadinessProfile {\n const profile = requireRecord(value, \"radiometryReadiness\", [\"schemaVersion\", \"components\"]);\n if (profile.schemaVersion !== \"0.1.0\") {\n throw new InvalidConfigurationError(\n 'radiometryReadiness.schemaVersion must be \"0.1.0\".'\n );\n }\n if (!Array.isArray(profile.components)) {\n throw new InvalidConfigurationError(\n \"radiometryReadiness.components must be an array.\"\n );\n }\n\n const components = profile.components.map((component, index) =>\n parseRequirement(\n component,\n `radiometryReadiness.components[${index}]`\n )\n );\n const ids = components.map((component) => component.requirement);\n if (new Set(ids).size !== ids.length) {\n throw new InvalidConfigurationError(\n \"radiometryReadiness.components must not contain duplicate requirement IDs.\"\n );\n }\n\n return {\n schemaVersion: \"0.1.0\",\n components\n };\n}\n\n/**\n * Checks whether the declared prerequisites are enough for a nominal photon\n * estimate and, separately, for a calibrated photon claim.\n *\n * It does not switch on composed photon or noise output.\n */\nexport function assessRadiometryReadiness(\n profile: RadiometryReadinessProfile\n): RadiometryReadinessAssessment {\n const validatedProfile = parseRadiometryReadinessProfile(profile);\n const byId = new Map(\n validatedProfile.components.map((component) => [\n component.requirement,\n component\n ])\n );\n const missingRequirements = REQUIRED_REQUIREMENTS.filter(\n (requirement) => !byId.has(requirement)\n );\n const approximateRequirements = validatedProfile.components\n .filter(\n (component) =>\n component.scientificStatus === \"approximation\"\n )\n .map((component) => component.requirement);\n const unquantifiedUncertaintyRequirements = validatedProfile.components\n .filter(\n (component) =>\n component.uncertainty.kind === \"not-quantified\"\n )\n .map((component) => component.requirement);\n\n const nominalPhotonEstimateReady = missingRequirements.length === 0;\n const calibratedPhotonClaimReady =\n nominalPhotonEstimateReady &&\n approximateRequirements.length === 0 &&\n unquantifiedUncertaintyRequirements.length === 0;\n\n return {\n status: !nominalPhotonEstimateReady\n ? \"not-ready\"\n : calibratedPhotonClaimReady\n ? \"calibrated-ready\"\n : \"approximate-only\",\n nominalPhotonEstimateReady,\n calibratedPhotonClaimReady,\n missingRequirements,\n approximateRequirements,\n unquantifiedUncertaintyRequirements,\n composedPhotonOutputEnabled: false\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"radiometry-readiness.js","sourceRoot":"","sources":["../../src/sensor/radiometry-readiness.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;GAQG;AAEH,OAAO,EACL,iBAAiB,EAElB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,0BAA0B,EAAE,0BAA0B,EAAE,mBAAmB,IAAI,aAAa,EAAE,yBAAyB,IAAI,aAAa,EAAE,MAAM,8BAA8B,CAAC;AACxL,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AA8IhE,MAAM,qBAAqB,GAAuC;IAChE,yBAAyB;IACzB,sBAAsB;IACtB,kBAAkB;IAClB,2BAA2B;IAC3B,sBAAsB;IACtB,iBAAiB;CAClB,CAAC;AAEF,MAAM,eAAe,GAAG,IAAI,GAAG,CAC7B,qBAAqB,CACtB,CAAC;AAEF,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAA6B;IAC9D,YAAY;IACZ,eAAe;CAChB,CAAC,CAAC;AAEH,SAAS,eAAe,CACtB,MAAqB,EACrB,GAAW,EACX,IAAY,EACZ,SAAkB;IAElB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,IACE,OAAO,KAAK,KAAK,QAAQ;QACzB,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QACvB,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QACpC,KAAK,GAAG,CAAC,EACT,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,GAAG,IAAI,IAAI,GAAG,8BAA8B,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,8BAA8B,GAAG,CAC/G,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,aAAa,CACpB,KAAc,EACd,IAAY;IAEZ,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC;IACpE,MAAM,EAAE,GAAG,aAAa,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7C,MAAM,cAAc,GAAG,aAAa,CAClC,MAAM,EACN,gBAAgB,EAChB,IAAI,CACL,CAAC;IACF,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,yBAAyB,CACjC,GAAG,IAAI,4DAA4D,CACpE,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,cAAc,EAAE,cAAc,CAAC,WAAW,EAAE,EAAE,CAAC;AAC9D,CAAC;AAED,SAAS,gBAAgB,CACvB,KAAc,EACd,IAAY;IAEZ,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAChD,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,0BAA0B,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACtI,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAEjD,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QACjC,IACE,OAAO,QAAQ,KAAK,QAAQ;YAC5B,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAC1B,QAAQ,GAAG,CAAC,EACZ,CAAC;YACD,MAAM,IAAI,yBAAyB,CACjC,GAAG,IAAI,6DAA6D,CACrE,CAAC;QACJ,CAAC;QACD,OAAO;YACL,IAAI;YACJ,QAAQ;YACR,KAAK,EAAE,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;SAC5C,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QACnC,IACE,OAAO,SAAS,KAAK,QAAQ;YAC7B,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;YAC3B,SAAS,GAAG,CAAC,EACb,CAAC;YACD,MAAM,IAAI,yBAAyB,CACjC,GAAG,IAAI,8DAA8D,CACtE,CAAC;QACJ,CAAC;QACD,OAAO;YACL,IAAI;YACJ,SAAS;YACT,IAAI,EAAE,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC;YACzC,KAAK,EAAE,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;SAC5C,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;QAC9B,OAAO;YACL,IAAI;YACJ,UAAU,EAAE,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,CAAC;SACtD,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,yBAAyB,CAAC,GAAG,IAAI,mBAAmB,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,SAAS,CAChB,MAAqB,EACrB,IAAY;IAEZ,MAAM,gBAAgB,GAAG,aAAa,CACpC,MAAM,EACN,kBAAkB,EAClB,IAAI,CACL,CAAC;IACF,IACE,CAAC,mBAAmB,CAAC,GAAG,CACtB,gBAA8C,CAC/C,EACD,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,GAAG,IAAI,+BAA+B,CACvC,CAAC;IACJ,CAAC;IAED,OAAO;QACL,gBAAgB,EACd,gBAA8C;QAChD,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC;QAC/C,YAAY,EAAE,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,CAAC;QACzD,QAAQ,EAAE,iBAAiB,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,IAAI,WAAW,CAAC;QAChE,WAAW,EAAE,gBAAgB,CAC3B,MAAM,CAAC,WAAW,EAClB,GAAG,IAAI,cAAc,CACtB;KACF,CAAC;AACJ,CAAC;AAED,SAAS,0BAA0B,CACjC,IAAoD,EACpD,IAAY,EACZ,cAAsB;IAEtB,IAAI,IAAI,CAAC,gBAAgB,KAAK,eAAe,EAAE,CAAC;QAC9C,MAAM,IAAI,yBAAyB,CACjC,GAAG,IAAI,gDAAgD,cAAc,sDAAsD,CAC5H,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CACvB,KAAc,EACd,IAAY;IAEZ,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,aAAa,EAAE,kBAAkB,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,4BAA4B,EAAE,4BAA4B,EAAE,0CAA0C,EAAE,oCAAoC,EAAE,YAAY,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,4BAA4B,CAAC,CAAC,CAAC;IACra,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;IAC/D,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAsC,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,yBAAyB,CACjC,GAAG,IAAI,0BAA0B,CAClC,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAErC,IAAI,WAAW,KAAK,yBAAyB,EAAE,CAAC;QAC9C,MAAM,cAAc,GAAG,aAAa,CAClC,MAAM,EACN,gBAAgB,EAChB,IAAI,CACL,CAAC;QACF,IACE,cAAc,KAAK,eAAe;YAClC,cAAc,KAAK,mCAAmC,EACtD,CAAC;YACD,MAAM,IAAI,yBAAyB,CACjC,GAAG,IAAI,6BAA6B,CACrC,CAAC;QACJ,CAAC;QACD,IAAI,cAAc,KAAK,mCAAmC,EAAE,CAAC;YAC3D,0BAA0B,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;QACzD,CAAC;QACD,OAAO;YACL,WAAW;YACX,GAAG,IAAI;YACP,cAAc;YACd,YAAY,EAAE,aAAa,CACzB,MAAM,CAAC,YAAY,EACnB,GAAG,IAAI,eAAe,CACvB;SACF,CAAC;IACJ,CAAC;IAED,IAAI,WAAW,KAAK,sBAAsB,EAAE,CAAC;QAC3C,MAAM,cAAc,GAAG,aAAa,CAClC,MAAM,EACN,gBAAgB,EAChB,IAAI,CACL,CAAC;QACF,IAAI,cAAc,KAAK,eAAe,EAAE,CAAC;YACvC,OAAO;gBACL,WAAW;gBACX,GAAG,IAAI;gBACP,cAAc;gBACd,YAAY,EAAE,aAAa,CACzB,MAAM,CAAC,YAAY,EACnB,GAAG,IAAI,eAAe,CACvB;aACF,CAAC;QACJ,CAAC;QACD,IAAI,cAAc,KAAK,sBAAsB,EAAE,CAAC;YAC9C,0BAA0B,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;YACvD,OAAO;gBACL,WAAW;gBACX,GAAG,IAAI;gBACP,cAAc;gBACd,KAAK,EAAE,qBAAqB,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;aACpD,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,GAAG,IAAI,6BAA6B,CACrC,CAAC;IACJ,CAAC;IAED,IAAI,WAAW,KAAK,kBAAkB,EAAE,CAAC;QACvC,MAAM,cAAc,GAAG,aAAa,CAClC,MAAM,EACN,gBAAgB,EAChB,IAAI,CACL,CAAC;QACF,IAAI,cAAc,KAAK,cAAc,EAAE,CAAC;YACtC,OAAO;gBACL,WAAW;gBACX,GAAG,IAAI;gBACP,cAAc;gBACd,YAAY,EAAE,aAAa,CACzB,MAAM,CAAC,YAAY,EACnB,GAAG,IAAI,eAAe,CACvB;aACF,CAAC;QACJ,CAAC;QACD,IAAI,cAAc,KAAK,0BAA0B,EAAE,CAAC;YAClD,0BAA0B,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;YACvD,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,cAAc,EAAE,CAAC;QAClD,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,GAAG,IAAI,6BAA6B,CACrC,CAAC;IACJ,CAAC;IAED,IAAI,WAAW,KAAK,2BAA2B,EAAE,CAAC;QAChD,IACE,MAAM,CAAC,SAAS,KAAK,SAAS;YAC9B,CAAC,MAAM,CAAC,0BAA0B,KAAK,SAAS;gBAC9C,MAAM,CAAC,0BAA0B,KAAK,SAAS,CAAC,EAClD,CAAC;YACD,MAAM,IAAI,yBAAyB,CACjC,GAAG,IAAI,gGAAgG,CACxG,CAAC;QACJ,CAAC;QACD,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;QAC3D,IAAI,SAAS,KAAK,2BAA2B,EAAE,CAAC;YAC9C,OAAO;gBACL,WAAW;gBACX,GAAG,IAAI;gBACP,SAAS;gBACT,wCAAwC,EACtC,qBAAqB,CACnB,MAAM,EACN,0CAA0C,EAC1C,IAAI,CACL;aACJ,CAAC;QACJ,CAAC;QACD,IAAI,SAAS,KAAK,kCAAkC,EAAE,CAAC;YACrD,OAAO;gBACL,WAAW;gBACX,GAAG,IAAI;gBACP,SAAS;gBACT,kCAAkC,EAChC,qBAAqB,CACnB,MAAM,EACN,oCAAoC,EACpC,IAAI,CACL;gBACH,UAAU,EAAE,eAAe,CACzB,MAAM,EACN,YAAY,EACZ,IAAI,EACJ,KAAK,CACN;aACF,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,GAAG,IAAI,+FAA+F,CACvG,CAAC;IACJ,CAAC;IAED,IAAI,WAAW,KAAK,sBAAsB,EAAE,CAAC;QAC3C,MAAM,gBAAgB,GAAG,aAAa,CACpC,MAAM,EACN,kBAAkB,EAClB,IAAI,CACL,CAAC;QACF,IAAI,gBAAgB,KAAK,gBAAgB,EAAE,CAAC;YAC1C,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,gBAAgB,EAAE,CAAC;QACpD,CAAC;QACD,IAAI,gBAAgB,KAAK,6BAA6B,EAAE,CAAC;YACvD,OAAO;gBACL,WAAW;gBACX,GAAG,IAAI;gBACP,gBAAgB;gBAChB,YAAY,EAAE,aAAa,CACzB,MAAM,CAAC,YAAY,EACnB,GAAG,IAAI,eAAe,CACvB;aACF,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,GAAG,IAAI,+BAA+B,CACvC,CAAC;IACJ,CAAC;IAED,MAAM,sBAAsB,GAAG,aAAa,CAC1C,MAAM,EACN,wBAAwB,EACxB,IAAI,CACL,CAAC;IACF,IAAI,sBAAsB,KAAK,6BAA6B,EAAE,CAAC;QAC7D,OAAO;YACL,WAAW,EAAE,iBAAiB;YAC9B,GAAG,IAAI;YACP,sBAAsB;YACtB,YAAY,EAAE,aAAa,CACzB,MAAM,CAAC,YAAY,EACnB,GAAG,IAAI,eAAe,CACvB;SACF,CAAC;IACJ,CAAC;IACD,IAAI,sBAAsB,KAAK,4BAA4B,EAAE,CAAC;QAC5D,0BAA0B,CAAC,IAAI,EAAE,IAAI,EAAE,sBAAsB,CAAC,CAAC;QAC/D,OAAO;YACL,WAAW,EAAE,iBAAiB;YAC9B,GAAG,IAAI;YACP,sBAAsB;YACtB,0BAA0B,EAAE,eAAe,CACzC,MAAM,EACN,4BAA4B,EAC5B,IAAI,EACJ,IAAI,CACL;SACF,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,yBAAyB,CACjC,GAAG,IAAI,qCAAqC,CAC7C,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,+BAA+B,CAC7C,KAAc;IAEd,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,EAAE,qBAAqB,EAAE,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC,CAAC;IAC7F,IAAI,OAAO,CAAC,aAAa,KAAK,OAAO,EAAE,CAAC;QACtC,MAAM,IAAI,yBAAyB,CACjC,oDAAoD,CACrD,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,yBAAyB,CACjC,kDAAkD,CACnD,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,CAC7D,gBAAgB,CACd,SAAS,EACT,kCAAkC,KAAK,GAAG,CAC3C,CACF,CAAC;IACF,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACjE,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC;QACrC,MAAM,IAAI,yBAAyB,CACjC,4EAA4E,CAC7E,CAAC;IACJ,CAAC;IAED,OAAO;QACL,aAAa,EAAE,OAAO;QACtB,UAAU;KACX,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAAmC;IAEnC,MAAM,gBAAgB,GAAG,+BAA+B,CAAC,OAAO,CAAC,CAAC;IAClE,MAAM,IAAI,GAAG,IAAI,GAAG,CAClB,gBAAgB,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC;QAC7C,SAAS,CAAC,WAAW;QACrB,SAAS;KACV,CAAC,CACH,CAAC;IACF,MAAM,mBAAmB,GAAG,qBAAqB,CAAC,MAAM,CACtD,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CACxC,CAAC;IACF,MAAM,uBAAuB,GAAG,gBAAgB,CAAC,UAAU;SACxD,MAAM,CACL,CAAC,SAAS,EAAE,EAAE,CACZ,SAAS,CAAC,gBAAgB,KAAK,eAAe,CACjD;SACA,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,mCAAmC,GAAG,gBAAgB,CAAC,UAAU;SACpE,MAAM,CACL,CAAC,SAAS,EAAE,EAAE,CACZ,SAAS,CAAC,WAAW,CAAC,IAAI,KAAK,gBAAgB,CAClD;SACA,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAE7C,MAAM,0BAA0B,GAAG,mBAAmB,CAAC,MAAM,KAAK,CAAC,CAAC;IACpE,MAAM,0BAA0B,GAC9B,0BAA0B;QAC1B,uBAAuB,CAAC,MAAM,KAAK,CAAC;QACpC,mCAAmC,CAAC,MAAM,KAAK,CAAC,CAAC;IAEnD,OAAO;QACL,MAAM,EAAE,CAAC,0BAA0B;YACjC,CAAC,CAAC,WAAW;YACb,CAAC,CAAC,0BAA0B;gBAC1B,CAAC,CAAC,kBAAkB;gBACpB,CAAC,CAAC,kBAAkB;QACxB,0BAA0B;QAC1B,0BAA0B;QAC1B,mBAAmB;QACnB,uBAAuB;QACvB,mCAAmC;QACnC,2BAA2B,EAAE,KAAK;KACnC,CAAC;AACJ,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Radiometry readiness: checks whether the declared prerequisites are enough for a nominal photon\n * estimate and, separately, for a calibrated photon claim.\n *\n * The parser checks structure and provenance. It cannot prove that a cited calibration or evidence\n * claim is true. Passing this check does not switch on composed photon or noise output.\n * @see docs/MOTION_AND_SIGNAL.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport { rejectUnknownVariantFields, UNCERTAINTY_VARIANT_FIELDS, requireConfigRecord as requireRecord, requireConfigRecordString as requireString } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requirePositiveNumber } from \"../schema/validation.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport type RadiometryRequirementId =\n | \"scene-spectral-radiance\"\n | \"optical-transmission\"\n | \"pupil-vignetting\"\n | \"photosite-collection-area\"\n | \"exposure-integration\"\n | \"sensor-response\";\n\nexport type RadiometryScientificStatus =\n | \"calibrated\"\n | \"approximation\";\n\nexport type RadiometryUncertaintyDeclaration =\n | {\n kind: \"relative\";\n fraction: number;\n basis: string;\n }\n | {\n kind: \"absolute\";\n plusMinus: number;\n unit: string;\n basis: string;\n }\n | {\n kind: \"not-quantified\";\n limitation: string;\n };\n\nexport interface CalibrationArtifactReference {\n id: string;\n checksumSha256: string;\n}\n\ninterface RadiometryRequirementBase {\n requirement: RadiometryRequirementId;\n scientificStatus: RadiometryScientificStatus;\n modelId: string;\n modelVersion: string;\n evidence: readonly EvidenceProvenance[];\n uncertainty: RadiometryUncertaintyDeclaration;\n}\n\nexport interface SceneSpectralRadianceRequirement\n extends RadiometryRequirementBase {\n requirement: \"scene-spectral-radiance\";\n representation:\n | \"spectral-data\"\n | \"documented-spectral-approximation\";\n dataArtifact: CalibrationArtifactReference;\n}\n\nexport type OpticalTransmissionRequirement =\n | (RadiometryRequirementBase & {\n requirement: \"optical-transmission\";\n representation: \"spectral-data\";\n dataArtifact: CalibrationArtifactReference;\n })\n | (RadiometryRequirementBase & {\n requirement: \"optical-transmission\";\n representation: \"t-stop-approximation\";\n tStop: number;\n });\n\nexport type PupilVignettingRequirement =\n | (RadiometryRequirementBase & {\n requirement: \"pupil-vignetting\";\n representation: \"spatial-data\";\n dataArtifact: CalibrationArtifactReference;\n })\n | (RadiometryRequirementBase & {\n requirement: \"pupil-vignetting\";\n representation: \"documented-approximation\";\n });\n\nexport type PhotositeCollectionAreaRequirement =\n | (RadiometryRequirementBase & {\n requirement: \"photosite-collection-area\";\n areaModel: \"effective-collection-area\";\n effectiveCollectionAreaSquareMicrometers: number;\n })\n | (RadiometryRequirementBase & {\n requirement: \"photosite-collection-area\";\n areaModel: \"geometric-area-times-fill-factor\";\n geometricCellAreaSquareMicrometers: number;\n fillFactor: number;\n });\n\nexport type ExposureIntegrationRequirement =\n | (RadiometryRequirementBase & {\n requirement: \"exposure-integration\";\n integrationModel: \"uniform-boxcar\";\n })\n | (RadiometryRequirementBase & {\n requirement: \"exposure-integration\";\n integrationModel: \"documented-shutter-function\";\n dataArtifact: CalibrationArtifactReference;\n });\n\nexport type SensorResponseRequirement =\n | (RadiometryRequirementBase & {\n requirement: \"sensor-response\";\n responseRepresentation: \"spectral-quantum-efficiency\";\n dataArtifact: CalibrationArtifactReference;\n })\n | (RadiometryRequirementBase & {\n requirement: \"sensor-response\";\n responseRepresentation: \"effective-qe-approximation\";\n effectiveQuantumEfficiency: number;\n });\n\nexport type RadiometryRequirement =\n | SceneSpectralRadianceRequirement\n | OpticalTransmissionRequirement\n | PupilVignettingRequirement\n | PhotositeCollectionAreaRequirement\n | ExposureIntegrationRequirement\n | SensorResponseRequirement;\n\nexport interface RadiometryReadinessProfile {\n schemaVersion: \"0.1.0\";\n components: readonly RadiometryRequirement[];\n}\n\nexport interface RadiometryReadinessAssessment {\n status: \"not-ready\" | \"approximate-only\" | \"calibrated-ready\";\n nominalPhotonEstimateReady: boolean;\n calibratedPhotonClaimReady: boolean;\n missingRequirements: readonly RadiometryRequirementId[];\n approximateRequirements: readonly RadiometryRequirementId[];\n unquantifiedUncertaintyRequirements: readonly RadiometryRequirementId[];\n /**\n * Always false: this assessment never switches on composed photon or noise\n * output by itself. Doing so is a separate, explicit later decision.\n */\n composedPhotonOutputEnabled: false;\n}\n\nconst REQUIRED_REQUIREMENTS: readonly RadiometryRequirementId[] = [\n \"scene-spectral-radiance\",\n \"optical-transmission\",\n \"pupil-vignetting\",\n \"photosite-collection-area\",\n \"exposure-integration\",\n \"sensor-response\"\n];\n\nconst REQUIREMENT_IDS = new Set<RadiometryRequirementId>(\n REQUIRED_REQUIREMENTS\n);\n\nconst SCIENTIFIC_STATUSES = new Set<RadiometryScientificStatus>([\n \"calibrated\",\n \"approximation\"\n]);\n\nfunction requireFraction(\n record: UnknownRecord,\n key: string,\n path: string,\n allowZero: boolean\n): number {\n const value = record[key];\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n (allowZero ? value < 0 : value <= 0) ||\n value > 1\n ) {\n throw new InvalidConfigurationError(\n `${path}.${key} must be a finite fraction ${allowZero ? \"from 0 through 1\" : \"greater than 0 and at most 1\"}.`\n );\n }\n return value;\n}\n\nfunction parseArtifact(\n value: unknown,\n path: string\n): CalibrationArtifactReference {\n const record = requireRecord(value, path, [\"id\", \"checksumSha256\"]);\n const id = requireString(record, \"id\", path);\n const checksumSha256 = requireString(\n record,\n \"checksumSha256\",\n path\n );\n if (!/^[a-f0-9]{64}$/iu.test(checksumSha256)) {\n throw new InvalidConfigurationError(\n `${path}.checksumSha256 must be a 64-character SHA-256 hex digest.`\n );\n }\n return { id, checksumSha256: checksumSha256.toLowerCase() };\n}\n\nfunction parseUncertainty(\n value: unknown,\n path: string\n): RadiometryUncertaintyDeclaration {\n const record = requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", { ...UNCERTAINTY_VARIANT_FIELDS, absolute: [\"kind\", \"plusMinus\", \"unit\", \"basis\"] }, path);\n const kind = requireString(record, \"kind\", path);\n\n if (kind === \"relative\") {\n const fraction = record.fraction;\n if (\n typeof fraction !== \"number\" ||\n !Number.isFinite(fraction) ||\n fraction < 0\n ) {\n throw new InvalidConfigurationError(\n `${path}.fraction must be finite and greater than or equal to zero.`\n );\n }\n return {\n kind,\n fraction,\n basis: requireString(record, \"basis\", path)\n };\n }\n\n if (kind === \"absolute\") {\n const plusMinus = record.plusMinus;\n if (\n typeof plusMinus !== \"number\" ||\n !Number.isFinite(plusMinus) ||\n plusMinus < 0\n ) {\n throw new InvalidConfigurationError(\n `${path}.plusMinus must be finite and greater than or equal to zero.`\n );\n }\n return {\n kind,\n plusMinus,\n unit: requireString(record, \"unit\", path),\n basis: requireString(record, \"basis\", path)\n };\n }\n\n if (kind === \"not-quantified\") {\n return {\n kind,\n limitation: requireString(record, \"limitation\", path)\n };\n }\n\n throw new InvalidConfigurationError(`${path}.kind is invalid.`);\n}\n\nfunction parseBase(\n record: UnknownRecord,\n path: string\n): Omit<RadiometryRequirementBase, \"requirement\"> {\n const scientificStatus = requireString(\n record,\n \"scientificStatus\",\n path\n );\n if (\n !SCIENTIFIC_STATUSES.has(\n scientificStatus as RadiometryScientificStatus\n )\n ) {\n throw new InvalidConfigurationError(\n `${path}.scientificStatus is invalid.`\n );\n }\n\n return {\n scientificStatus:\n scientificStatus as RadiometryScientificStatus,\n modelId: requireString(record, \"modelId\", path),\n modelVersion: requireString(record, \"modelVersion\", path),\n evidence: parseEvidenceList(record.evidence, `${path}.evidence`),\n uncertainty: parseUncertainty(\n record.uncertainty,\n `${path}.uncertainty`\n )\n };\n}\n\nfunction requireApproximationStatus(\n base: Omit<RadiometryRequirementBase, \"requirement\">,\n path: string,\n representation: string\n): void {\n if (base.scientificStatus !== \"approximation\") {\n throw new InvalidConfigurationError(\n `${path} uses inherently approximate representation \"${representation}\" and must declare scientificStatus \"approximation\".`\n );\n }\n}\n\nfunction parseRequirement(\n value: unknown,\n path: string\n): RadiometryRequirement {\n const record = requireRecord(value, path, [\"requirement\", \"scientificStatus\", \"modelId\", \"modelVersion\", \"evidence\", \"uncertainty\", \"representation\", \"dataArtifact\", \"tStop\", \"areaModel\", \"geometricPitchXMicrometers\", \"geometricPitchYMicrometers\", \"effectiveCollectionAreaSquareMicrometers\", \"geometricCellAreaSquareMicrometers\", \"fillFactor\", \"integrationModel\", \"responseRepresentation\", \"effectiveQuantumEfficiency\"]);\n const requirement = requireString(record, \"requirement\", path);\n if (!REQUIREMENT_IDS.has(requirement as RadiometryRequirementId)) {\n throw new InvalidConfigurationError(\n `${path}.requirement is invalid.`\n );\n }\n\n const base = parseBase(record, path);\n\n if (requirement === \"scene-spectral-radiance\") {\n const representation = requireString(\n record,\n \"representation\",\n path\n );\n if (\n representation !== \"spectral-data\" &&\n representation !== \"documented-spectral-approximation\"\n ) {\n throw new InvalidConfigurationError(\n `${path}.representation is invalid.`\n );\n }\n if (representation === \"documented-spectral-approximation\") {\n requireApproximationStatus(base, path, representation);\n }\n return {\n requirement,\n ...base,\n representation,\n dataArtifact: parseArtifact(\n record.dataArtifact,\n `${path}.dataArtifact`\n )\n };\n }\n\n if (requirement === \"optical-transmission\") {\n const representation = requireString(\n record,\n \"representation\",\n path\n );\n if (representation === \"spectral-data\") {\n return {\n requirement,\n ...base,\n representation,\n dataArtifact: parseArtifact(\n record.dataArtifact,\n `${path}.dataArtifact`\n )\n };\n }\n if (representation === \"t-stop-approximation\") {\n requireApproximationStatus(base, path, representation);\n return {\n requirement,\n ...base,\n representation,\n tStop: requirePositiveNumber(record, \"tStop\", path)\n };\n }\n throw new InvalidConfigurationError(\n `${path}.representation is invalid.`\n );\n }\n\n if (requirement === \"pupil-vignetting\") {\n const representation = requireString(\n record,\n \"representation\",\n path\n );\n if (representation === \"spatial-data\") {\n return {\n requirement,\n ...base,\n representation,\n dataArtifact: parseArtifact(\n record.dataArtifact,\n `${path}.dataArtifact`\n )\n };\n }\n if (representation === \"documented-approximation\") {\n requireApproximationStatus(base, path, representation);\n return { requirement, ...base, representation };\n }\n throw new InvalidConfigurationError(\n `${path}.representation is invalid.`\n );\n }\n\n if (requirement === \"photosite-collection-area\") {\n if (\n record.areaModel === undefined &&\n (record.geometricPitchXMicrometers !== undefined ||\n record.geometricPitchYMicrometers !== undefined)\n ) {\n throw new InvalidConfigurationError(\n `${path}.areaModel is required. Geometric sample pitch alone is not a photosite collection-area model.`\n );\n }\n const areaModel = requireString(record, \"areaModel\", path);\n if (areaModel === \"effective-collection-area\") {\n return {\n requirement,\n ...base,\n areaModel,\n effectiveCollectionAreaSquareMicrometers:\n requirePositiveNumber(\n record,\n \"effectiveCollectionAreaSquareMicrometers\",\n path\n )\n };\n }\n if (areaModel === \"geometric-area-times-fill-factor\") {\n return {\n requirement,\n ...base,\n areaModel,\n geometricCellAreaSquareMicrometers:\n requirePositiveNumber(\n record,\n \"geometricCellAreaSquareMicrometers\",\n path\n ),\n fillFactor: requireFraction(\n record,\n \"fillFactor\",\n path,\n false\n )\n };\n }\n throw new InvalidConfigurationError(\n `${path}.areaModel is invalid. Geometric sample pitch alone is not a photosite collection-area model.`\n );\n }\n\n if (requirement === \"exposure-integration\") {\n const integrationModel = requireString(\n record,\n \"integrationModel\",\n path\n );\n if (integrationModel === \"uniform-boxcar\") {\n return { requirement, ...base, integrationModel };\n }\n if (integrationModel === \"documented-shutter-function\") {\n return {\n requirement,\n ...base,\n integrationModel,\n dataArtifact: parseArtifact(\n record.dataArtifact,\n `${path}.dataArtifact`\n )\n };\n }\n throw new InvalidConfigurationError(\n `${path}.integrationModel is invalid.`\n );\n }\n\n const responseRepresentation = requireString(\n record,\n \"responseRepresentation\",\n path\n );\n if (responseRepresentation === \"spectral-quantum-efficiency\") {\n return {\n requirement: \"sensor-response\",\n ...base,\n responseRepresentation,\n dataArtifact: parseArtifact(\n record.dataArtifact,\n `${path}.dataArtifact`\n )\n };\n }\n if (responseRepresentation === \"effective-qe-approximation\") {\n requireApproximationStatus(base, path, responseRepresentation);\n return {\n requirement: \"sensor-response\",\n ...base,\n responseRepresentation,\n effectiveQuantumEfficiency: requireFraction(\n record,\n \"effectiveQuantumEfficiency\",\n path,\n true\n )\n };\n }\n throw new InvalidConfigurationError(\n `${path}.responseRepresentation is invalid.`\n );\n}\n\n/**\n * Parses untrusted metadata about radiometry prerequisites.\n *\n * It checks structure and provenance. It cannot prove that a cited calibration\n * or evidence claim is scientifically true.\n */\nexport function parseRadiometryReadinessProfile(\n value: unknown\n): RadiometryReadinessProfile {\n const profile = requireRecord(value, \"radiometryReadiness\", [\"schemaVersion\", \"components\"]);\n if (profile.schemaVersion !== \"0.1.0\") {\n throw new InvalidConfigurationError(\n 'radiometryReadiness.schemaVersion must be \"0.1.0\".'\n );\n }\n if (!Array.isArray(profile.components)) {\n throw new InvalidConfigurationError(\n \"radiometryReadiness.components must be an array.\"\n );\n }\n\n const components = profile.components.map((component, index) =>\n parseRequirement(\n component,\n `radiometryReadiness.components[${index}]`\n )\n );\n const ids = components.map((component) => component.requirement);\n if (new Set(ids).size !== ids.length) {\n throw new InvalidConfigurationError(\n \"radiometryReadiness.components must not contain duplicate requirement IDs.\"\n );\n }\n\n return {\n schemaVersion: \"0.1.0\",\n components\n };\n}\n\n/**\n * Checks whether the declared prerequisites are enough for a nominal photon\n * estimate and, separately, for a calibrated photon claim.\n *\n * It does not switch on composed photon or noise output.\n */\nexport function assessRadiometryReadiness(\n profile: RadiometryReadinessProfile\n): RadiometryReadinessAssessment {\n const validatedProfile = parseRadiometryReadinessProfile(profile);\n const byId = new Map(\n validatedProfile.components.map((component) => [\n component.requirement,\n component\n ])\n );\n const missingRequirements = REQUIRED_REQUIREMENTS.filter(\n (requirement) => !byId.has(requirement)\n );\n const approximateRequirements = validatedProfile.components\n .filter(\n (component) =>\n component.scientificStatus === \"approximation\"\n )\n .map((component) => component.requirement);\n const unquantifiedUncertaintyRequirements = validatedProfile.components\n .filter(\n (component) =>\n component.uncertainty.kind === \"not-quantified\"\n )\n .map((component) => component.requirement);\n\n const nominalPhotonEstimateReady = missingRequirements.length === 0;\n const calibratedPhotonClaimReady =\n nominalPhotonEstimateReady &&\n approximateRequirements.length === 0 &&\n unquantifiedUncertaintyRequirements.length === 0;\n\n return {\n status: !nominalPhotonEstimateReady\n ? \"not-ready\"\n : calibratedPhotonClaimReady\n ? \"calibrated-ready\"\n : \"approximate-only\",\n nominalPhotonEstimateReady,\n calibratedPhotonClaimReady,\n missingRequirements,\n approximateRequirements,\n unquantifiedUncertaintyRequirements,\n composedPhotonOutputEnabled: false\n };\n}\n"]}
|
|
@@ -299,6 +299,9 @@ export interface SensorRawCodeSample {
|
|
|
299
299
|
isoUsedToInferRegime: false;
|
|
300
300
|
deterministicSeededRealization: true;
|
|
301
301
|
}
|
|
302
|
+
export declare function requireSafeInteger(value: unknown, path: string): number;
|
|
303
|
+
export declare function parsePositiveFact(value: unknown, path: string): EvidenceBackedFact<number>;
|
|
304
|
+
export declare function parseNonNegativeFact(value: unknown, path: string): EvidenceBackedFact<number>;
|
|
302
305
|
/**
|
|
303
306
|
* Validates untrusted input and returns it as a normalized, typed value. Unknown enum values,
|
|
304
307
|
* missing required fields and inconsistent scientific data are rejected.
|
|
@@ -24,50 +24,10 @@ import { parseEvidenceList } from "../core/evidence-provenance.js";
|
|
|
24
24
|
import { InvalidScientificInputError } from "../core/validation.js";
|
|
25
25
|
import { createDeterministicUniformStream, sampleDeterministicStandardNormal, samplePortableStandardNormal } from "./stochastic-seed.js";
|
|
26
26
|
import { portableExp, portableLog } from "../core/portable-math.js";
|
|
27
|
-
import { requireInputKeys,
|
|
27
|
+
import { requireInputKeys, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, requireConfigFinite as requireFinite, parseConfigScientificStatus as parseStatus, parseConfigLimitations as parseLimitations, requireConfigFiniteAboveZero as requirePositiveFinite, requireConfigFiniteAtLeastZero as requireNonNegativeFinite } from "../core/record-validation.js";
|
|
28
28
|
import { evaluateParsedFixedPatternSite, parseSensorFixedPatternNoiseProfile } from "./fixed-pattern-noise.js";
|
|
29
29
|
export const SENSOR_CHARGE_SAMPLING_PROFILE_SCHEMA_VERSION = "0.1.0";
|
|
30
30
|
export const SENSOR_READOUT_CONVERSION_PROFILE_SCHEMA_VERSION = "0.1.0";
|
|
31
|
-
function requireRecord(value, path, allowedKeys) {
|
|
32
|
-
if (typeof value !== "object" ||
|
|
33
|
-
value === null ||
|
|
34
|
-
Array.isArray(value)) {
|
|
35
|
-
throw new InvalidConfigurationError(path + " must be an object.");
|
|
36
|
-
}
|
|
37
|
-
if (allowedKeys !== null)
|
|
38
|
-
rejectUnknownFields(value, allowedKeys, path);
|
|
39
|
-
return value;
|
|
40
|
-
}
|
|
41
|
-
function requireNonEmptyString(value, path) {
|
|
42
|
-
if (typeof value !== "string" ||
|
|
43
|
-
value.trim().length === 0) {
|
|
44
|
-
throw new InvalidConfigurationError(path + " must be a non-empty string.");
|
|
45
|
-
}
|
|
46
|
-
return value.trim();
|
|
47
|
-
}
|
|
48
|
-
function requireFinite(value, path) {
|
|
49
|
-
if (typeof value !== "number" ||
|
|
50
|
-
!Number.isFinite(value)) {
|
|
51
|
-
throw new InvalidConfigurationError(path + " must be finite.");
|
|
52
|
-
}
|
|
53
|
-
return value;
|
|
54
|
-
}
|
|
55
|
-
function requireNonNegativeFinite(value, path) {
|
|
56
|
-
const parsed = requireFinite(value, path);
|
|
57
|
-
if (parsed < 0) {
|
|
58
|
-
throw new InvalidConfigurationError(path +
|
|
59
|
-
" must be greater than or equal to zero.");
|
|
60
|
-
}
|
|
61
|
-
return parsed;
|
|
62
|
-
}
|
|
63
|
-
function requirePositiveFinite(value, path) {
|
|
64
|
-
const parsed = requireFinite(value, path);
|
|
65
|
-
if (parsed <= 0) {
|
|
66
|
-
throw new InvalidConfigurationError(path +
|
|
67
|
-
" must be greater than zero.");
|
|
68
|
-
}
|
|
69
|
-
return parsed;
|
|
70
|
-
}
|
|
71
31
|
function requireUint32(value, path) {
|
|
72
32
|
if (typeof value !== "number" ||
|
|
73
33
|
!Number.isSafeInteger(value) ||
|
|
@@ -78,36 +38,21 @@ function requireUint32(value, path) {
|
|
|
78
38
|
}
|
|
79
39
|
return value;
|
|
80
40
|
}
|
|
81
|
-
function requireSafeInteger(value, path) {
|
|
41
|
+
export function requireSafeInteger(value, path) {
|
|
82
42
|
if (typeof value !== "number" ||
|
|
83
43
|
!Number.isSafeInteger(value)) {
|
|
84
44
|
throw new InvalidConfigurationError(path + " must be a safe integer.");
|
|
85
45
|
}
|
|
86
46
|
return value;
|
|
87
47
|
}
|
|
88
|
-
function
|
|
89
|
-
if (!Array.isArray(value)) {
|
|
90
|
-
throw new InvalidConfigurationError(path + " must be an array.");
|
|
91
|
-
}
|
|
92
|
-
const parsed = value.map((entry, index) => requireNonEmptyString(entry, path +
|
|
93
|
-
"[" +
|
|
94
|
-
index +
|
|
95
|
-
"]"));
|
|
96
|
-
if (new Set(parsed).size !==
|
|
97
|
-
parsed.length) {
|
|
98
|
-
throw new InvalidConfigurationError(path +
|
|
99
|
-
" must not contain duplicates.");
|
|
100
|
-
}
|
|
101
|
-
return parsed;
|
|
102
|
-
}
|
|
103
|
-
function parsePositiveFact(value, path) {
|
|
48
|
+
export function parsePositiveFact(value, path) {
|
|
104
49
|
const record = requireRecord(value, path, ["value", "evidence"]);
|
|
105
50
|
return {
|
|
106
51
|
value: requirePositiveFinite(record.value, path + ".value"),
|
|
107
52
|
evidence: parseEvidenceList(record.evidence, path + ".evidence")
|
|
108
53
|
};
|
|
109
54
|
}
|
|
110
|
-
function parseNonNegativeFact(value, path) {
|
|
55
|
+
export function parseNonNegativeFact(value, path) {
|
|
111
56
|
const record = requireRecord(value, path, ["value", "evidence"]);
|
|
112
57
|
return {
|
|
113
58
|
value: requireNonNegativeFinite(record.value, path + ".value"),
|
|
@@ -180,13 +125,6 @@ export function parseSensorChargeSamplingProfile(value) {
|
|
|
180
125
|
limitations: parseLimitations(record.limitations, "sensorChargeSamplingProfile.limitations")
|
|
181
126
|
};
|
|
182
127
|
}
|
|
183
|
-
function parseStatus(value, path) {
|
|
184
|
-
if (value !== "calibrated" &&
|
|
185
|
-
value !== "approximation") {
|
|
186
|
-
throw new InvalidConfigurationError(path + " is invalid.");
|
|
187
|
-
}
|
|
188
|
-
return value;
|
|
189
|
-
}
|
|
190
128
|
function parseReadNoiseComponent(value, path) {
|
|
191
129
|
const record = requireRecord(value, path, ["componentId", "rmsElectrons", "evidence"]);
|
|
192
130
|
return {
|