@photivra/engine 2.19.0 → 2.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +289 -1
- package/CITATION.cff +1 -1
- package/NODE_SUPPORT.md +7 -5
- package/README.md +7 -6
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +21 -10
- package/dist/capture/dng-lens-correction-opcodes.d.ts +32 -0
- package/dist/capture/dng-lens-correction-opcodes.js +119 -0
- package/dist/capture/dng-lens-correction-opcodes.js.map +1 -0
- package/dist/capture/exposure-build-up-stage.d.ts +16 -0
- package/dist/capture/exposure-build-up-stage.js +4 -0
- package/dist/capture/exposure-build-up-stage.js.map +1 -0
- package/dist/capture/native-environment-lean.d.ts +2 -1
- package/dist/capture/native-environment-lean.js +42 -78
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-environment-tabulated.js +4 -3
- package/dist/capture/native-environment-tabulated.js.map +1 -1
- package/dist/capture/native-raw-dng.d.ts +6 -0
- package/dist/capture/native-raw-dng.js +16 -2
- package/dist/capture/native-raw-dng.js.map +1 -1
- package/dist/capture/native-raw.d.ts +3 -2
- package/dist/capture/native-raw.js +5 -4
- package/dist/capture/native-raw.js.map +1 -1
- package/dist/capture/sensor-raw-producer.d.ts +4 -1
- package/dist/capture/sensor-raw-producer.js +15 -8
- package/dist/capture/sensor-raw-producer.js.map +1 -1
- package/dist/core/shared-helpers.d.ts +2 -0
- package/dist/core/shared-helpers.js +4 -0
- package/dist/core/shared-helpers.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/generic-lens-catalogue.d.ts +11 -4
- package/dist/equipment/generic-lens-catalogue.js +49 -7
- package/dist/equipment/generic-lens-catalogue.js.map +1 -1
- package/dist/equipment/generic-tier-assets.d.ts +32 -0
- package/dist/equipment/generic-tier-assets.js +18 -14
- package/dist/equipment/generic-tier-assets.js.map +1 -1
- package/dist/equipment/generic-tier-presets.js +2 -3
- package/dist/equipment/generic-tier-presets.js.map +1 -1
- package/dist/equipment/sensor-profile-body.d.ts +78 -0
- package/dist/equipment/sensor-profile-body.js +77 -0
- package/dist/equipment/sensor-profile-body.js.map +1 -0
- package/dist/equipment/sensor-profiles.d.ts +8 -0
- package/dist/equipment/sensor-profiles.js +82 -0
- package/dist/equipment/sensor-profiles.js.map +1 -0
- package/dist/facade/catalogue-lens-signal.d.ts +2 -2
- package/dist/facade/catalogue-lens-signal.js +58 -71
- package/dist/facade/catalogue-lens-signal.js.map +1 -1
- package/dist/facade/chart-radiance-batch.js +2 -1
- package/dist/facade/chart-radiance-batch.js.map +1 -1
- package/dist/facade/defocus-image-space-provider.d.ts +7 -0
- package/dist/facade/defocus-image-space-provider.js +64 -76
- package/dist/facade/defocus-image-space-provider.js.map +1 -1
- package/dist/facade/display-view-gpu-session.js +2 -0
- package/dist/facade/display-view-gpu-session.js.map +1 -1
- package/dist/facade/display-view-gpu.d.ts +13 -5
- package/dist/facade/display-view-gpu.js +4 -4
- package/dist/facade/display-view-gpu.js.map +1 -1
- package/dist/facade/display-view-lens-signal.d.ts +1 -1
- package/dist/facade/display-view-lens-signal.js +30 -26
- package/dist/facade/display-view-lens-signal.js.map +1 -1
- package/dist/facade/display-view.d.ts +3 -1
- package/dist/facade/display-view.js +6 -24
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/expected-signal-setup.d.ts +3 -1
- package/dist/facade/expected-signal-setup.js +1 -1
- package/dist/facade/expected-signal-setup.js.map +1 -1
- package/dist/facade/expected-signal.d.ts +47 -14
- package/dist/facade/expected-signal.js +117 -112
- package/dist/facade/expected-signal.js.map +1 -1
- package/dist/facade/exposure-build-up.d.ts +70 -0
- package/dist/facade/exposure-build-up.js +164 -0
- package/dist/facade/exposure-build-up.js.map +1 -0
- package/dist/facade/fast-methods.d.ts +50 -0
- package/dist/facade/fast-methods.js +58 -0
- package/dist/facade/fast-methods.js.map +1 -0
- package/dist/facade/fast-resolution.d.ts +12 -0
- package/dist/facade/fast-resolution.js +18 -0
- package/dist/facade/fast-resolution.js.map +1 -0
- package/dist/facade/generic-lens-capture.d.ts +5 -4
- package/dist/facade/generic-lens-capture.js +5 -4
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/image-plane-enable.d.ts +7 -0
- package/dist/facade/image-plane-enable.js +17 -0
- package/dist/facade/image-plane-enable.js.map +1 -0
- package/dist/facade/image-plane-lattice-data.d.ts +6 -0
- package/dist/facade/image-plane-lattice-data.js +10 -0
- package/dist/facade/image-plane-lattice-data.js.map +1 -0
- package/dist/facade/image-plane-support.d.ts +33 -0
- package/dist/facade/image-plane-support.js +11 -0
- package/dist/facade/image-plane-support.js.map +1 -0
- package/dist/facade/image-plane.d.ts +36 -0
- package/dist/facade/image-plane.js +353 -0
- package/dist/facade/image-plane.js.map +1 -0
- package/dist/facade/mixed-illumination.d.ts +108 -0
- package/dist/facade/mixed-illumination.js +174 -0
- package/dist/facade/mixed-illumination.js.map +1 -0
- package/dist/facade/representative-light-sources.d.ts +72 -0
- package/dist/facade/representative-light-sources.js +124 -0
- package/dist/facade/representative-light-sources.js.map +1 -0
- package/dist/facade/scene-radiance.d.ts +129 -4
- package/dist/facade/scene-radiance.js +48 -13
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +88 -19
- package/dist/facade/simulate-capture.js +374 -145
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.d.ts +3 -2
- package/dist/facade/simulate-display-view.js +36 -18
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.d.ts +13 -1
- package/dist/gpu/chart-composite-gpu.js +48 -9
- package/dist/gpu/chart-composite-gpu.js.map +1 -1
- package/dist/gpu/chart-radiance-gpu.js +4 -30
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/gpu/display-view-composite-material-module.d.ts +10 -4
- package/dist/gpu/display-view-composite-material-module.js +39 -13
- package/dist/gpu/display-view-composite-material-module.js.map +1 -1
- package/dist/gpu/display-view-image-material-module.d.ts +86 -0
- package/dist/gpu/display-view-image-material-module.js +339 -0
- package/dist/gpu/display-view-image-material-module.js.map +1 -0
- package/dist/gpu/display-view-image-quality.d.ts +45 -0
- package/dist/gpu/display-view-image-quality.js +380 -0
- package/dist/gpu/display-view-image-quality.js.map +1 -0
- package/dist/gpu/display-view-quality-gpu.d.ts +67 -1
- package/dist/gpu/display-view-quality-gpu.js +136 -205
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.d.ts +51 -3
- package/dist/gpu/display-view-speed-gpu.js +131 -93
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +29 -15
- package/dist/gpu/wgsl-display-view-quality-kernel.js +58 -36
- package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +21 -6
- package/dist/gpu/wgsl-display-view-speed-kernel.js +46 -11
- package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
- package/dist/gpu/wgsl-exact-sum.d.ts +20 -0
- package/dist/gpu/wgsl-exact-sum.js +42 -0
- package/dist/gpu/wgsl-exact-sum.js.map +1 -0
- package/dist/index.d.ts +18 -3
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/motion/subject-motion.d.ts +66 -0
- package/dist/motion/subject-motion.js +52 -0
- package/dist/motion/subject-motion.js.map +1 -0
- package/dist/optics/aperture-diameter.d.ts +47 -0
- package/dist/optics/aperture-diameter.js +50 -0
- package/dist/optics/aperture-diameter.js.map +1 -0
- package/dist/optics/detail-limit.d.ts +182 -0
- package/dist/optics/detail-limit.js +336 -0
- package/dist/optics/detail-limit.js.map +1 -0
- package/dist/optics/generic-lens-lateral-color.d.ts +83 -0
- package/dist/optics/generic-lens-lateral-color.js +77 -0
- package/dist/optics/generic-lens-lateral-color.js.map +1 -0
- package/dist/optics/generic-lens-psf.d.ts +18 -2
- package/dist/optics/generic-lens-psf.js +79 -48
- package/dist/optics/generic-lens-psf.js.map +1 -1
- package/dist/optics/lens-psf-profile.d.ts +7 -0
- package/dist/optics/lens-psf-profile.js +2 -1
- package/dist/optics/lens-psf-profile.js.map +1 -1
- package/dist/optics/scene-to-sensor-irradiance.d.ts +13 -0
- package/dist/optics/scene-to-sensor-irradiance.js +7 -0
- package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
- package/dist/output/crop-to-match-focal-length.d.ts +62 -0
- package/dist/output/crop-to-match-focal-length.js +63 -0
- package/dist/output/crop-to-match-focal-length.js.map +1 -0
- package/dist/output/developed-lens-corrections.d.ts +19 -5
- package/dist/output/developed-lens-corrections.js +30 -11
- package/dist/output/developed-lens-corrections.js.map +1 -1
- package/dist/output/generic-lens-corrections.d.ts +41 -3
- package/dist/output/generic-lens-corrections.js +57 -9
- package/dist/output/generic-lens-corrections.js.map +1 -1
- package/dist/output/lens-corrections.d.ts +12 -2
- package/dist/output/lens-corrections.js +22 -7
- package/dist/output/lens-corrections.js.map +1 -1
- package/dist/output/print-contrast-reference.js +1 -1
- package/dist/output/print-contrast-reference.js.map +1 -1
- package/dist/output/print-plan.d.ts +41 -5
- package/dist/output/print-plan.js +59 -14
- package/dist/output/print-plan.js.map +1 -1
- package/dist/output/print-size-blur-noise.d.ts +110 -0
- package/dist/output/print-size-blur-noise.js +138 -0
- package/dist/output/print-size-blur-noise.js.map +1 -0
- package/dist/sensor/binomial-sample.d.ts +3 -0
- package/dist/sensor/binomial-sample.js +86 -0
- package/dist/sensor/binomial-sample.js.map +1 -0
- package/dist/sensor/eqe-electron-rate.js +1 -7
- package/dist/sensor/eqe-electron-rate.js.map +1 -1
- package/dist/sensor/exposure-window.d.ts +2 -0
- package/dist/sensor/exposure-window.js +2 -2
- package/dist/sensor/exposure-window.js.map +1 -1
- package/dist/sensor/readout-timing.js +2 -23
- package/dist/sensor/readout-timing.js.map +1 -1
- package/dist/sensor/response-application-compatibility.js +1 -6
- package/dist/sensor/response-application-compatibility.js.map +1 -1
- package/dist/sensor/responsivity-photocurrent.js +1 -7
- package/dist/sensor/responsivity-photocurrent.js.map +1 -1
- package/dist/sensor/sensor-characteristics.d.ts +147 -0
- package/dist/sensor/sensor-characteristics.js +126 -0
- package/dist/sensor/sensor-characteristics.js.map +1 -0
- package/dist/sensor/spatial-sample-reduction.js +1 -5
- package/dist/sensor/spatial-sample-reduction.js.map +1 -1
- package/dist/sensor/spectral-quadrature.js +1 -6
- package/dist/sensor/spectral-quadrature.js.map +1 -1
- package/dist/sensor/temporal-photo-signal.d.ts +3 -0
- package/dist/sensor/temporal-photo-signal.js +5 -2
- package/dist/sensor/temporal-photo-signal.js.map +1 -1
- package/dist/stabilization/system.d.ts +9 -0
- package/dist/stabilization/system.js +5 -6
- package/dist/stabilization/system.js.map +1 -1
- package/docs/AGENT_GUIDE.md +5 -0
- package/docs/API_REFERENCE.md +173 -2
- package/docs/QUICK_START.md +213 -6
- package/docs/USAGE.md +157 -3
- package/docs/api/capture-native-raw-dng.md +6 -0
- package/docs/api/core-version.md +1 -1
- package/docs/api/equipment-generic-lens-catalogue.md +17 -7
- package/docs/api/equipment-sensor-profile-body.md +64 -0
- package/docs/api/equipment-sensor-profiles.md +86 -0
- package/docs/api/exports.json +357 -2
- package/docs/api/facade-display-view-gpu.md +5 -2
- package/docs/api/facade-exposure-build-up.md +105 -0
- package/docs/api/facade-fast-methods.md +99 -0
- package/docs/api/facade-image-plane-enable.md +16 -0
- package/docs/api/facade-mixed-illumination.md +67 -0
- package/docs/api/facade-representative-light-sources.md +131 -0
- package/docs/api/facade-scene-radiance.md +54 -3
- package/docs/api/facade-simulate-capture.md +60 -15
- package/docs/api/facade-simulate-display-view.md +3 -2
- package/docs/api/motion-subject-motion.md +23 -0
- package/docs/api/optics-aperture-diameter.md +51 -0
- package/docs/api/optics-detail-limit.md +203 -0
- package/docs/api/optics-generic-lens-lateral-color.md +79 -0
- package/docs/api/output-crop-to-match-focal-length.md +67 -0
- package/docs/api/output-developed-lens-corrections.md +10 -1
- package/docs/api/output-generic-lens-corrections.md +40 -2
- package/docs/api/output-lens-corrections.md +11 -1
- package/docs/api/output-print-plan.md +35 -1
- package/docs/api/output-print-size-blur-noise.md +115 -0
- package/docs/api/sensor-sensor-characteristics.md +105 -0
- package/llms.txt +6 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readout-timing.js","sourceRoot":"","sources":["../../src/sensor/readout-timing.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Sensor readout timing: when each position on the sensor is read out during one capture.\n *\n * Rolling readout is modelled as a uniform linear scan along one axis of the declared active capture.\n * The caller supplies the scan's time span (skew) explicitly. It is never worked out from the total\n * data-readout time, the crop size, pixel density, output resolution, sensor-architecture metadata or\n * the shutter mechanism. Global readout has no skew in this model, even when a non-zero data-readout\n * time is declared.\n *\n * Not covered here: local exposure start and end times, mechanical curtain travel, EFCS (electronic\n * first-curtain shutter) behaviour, rolling-shutter image distortion, flash or flicker, and motion\n * integration.\n * @see docs/MOTION_AND_SIGNAL.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport { approximationResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport {\n parseEvidenceList,\n type EvidenceBackedFact\n} from \"../core/evidence-provenance.js\";\nimport { InvalidScientificInputError, requirePositiveInteger } from \"../core/validation.js\";\nimport type { RasterPoint, RasterRect } from \"../output/capture-geometry.js\";\nimport type { NativeImageRaster } from \"./sensor-geometry.js\";\nimport type { SensorReadoutArchitecture } from \"./architecture.js\";\nimport { requireInputKeys, requireConfigRecord as requireRecord } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { fullRect } from \"../core/shared-helpers.js\";\nimport { normalizedScanPosition, validateNativeRaster, scanVector, requirePositiveFinite, requireNonNegativeInteger } from \"./exposure-window.js\";\n\n/**\n * The readout mode chosen for one capture.\n *\n * It uses the same names as the architecture metadata, but does not claim the\n * hardware supports it. SensorArchitectureProfile.readoutCapabilities is\n * descriptive only and is not checked automatically.\n */\nexport type SensorReadoutMode = SensorReadoutArchitecture;\n\nexport type NativeSensorReadoutScanDirection =\n | \"top-to-bottom\"\n | \"bottom-to-top\"\n | \"left-to-right\"\n | \"right-to-left\";\n\nexport type CaptureShutterMechanism =\n | \"mechanical\"\n | \"electronic-first-curtain\"\n | \"electronic\";\n\n/**\n * Evidence-backed timing value with an explicit seconds unit.\n */\nexport interface SourcedSensorTimingSeconds\n extends EvidenceBackedFact<number> {\n unit: \"s\";\n}\n\nexport type SourcedSensorReadoutFact<T> = EvidenceBackedFact<T>;\n\nexport interface GlobalSensorReadoutTimingDeclaration {\n readoutMode: \"global\";\n /**\n * Sensor data-readout time for this capture.\n *\n * It is deliberately not treated as the spatial exposure or readout skew.\n */\n captureReadoutDurationSeconds: SourcedSensorTimingSeconds;\n scanDirectionNative?: never;\n spatialSamplingSkewSeconds?: never;\n}\n\nexport interface RollingSensorReadoutTimingDeclaration {\n readoutMode: \"rolling\";\n /**\n * Sensor data-readout time for this capture.\n *\n * It is kept separate from the spatial skew, because a published readout time\n * and the scan's time span are not necessarily the same quantity.\n */\n captureReadoutDurationSeconds: SourcedSensorTimingSeconds;\n /**\n * Native-sensor scan direction for the selected capture mode.\n */\n scanDirectionNative: SourcedSensorReadoutFact<NativeSensorReadoutScanDirection>;\n /**\n * Time between the first and last scan positions, in the uniform linear\n * timing approximation (the readout skew).\n */\n spatialSamplingSkewSeconds: SourcedSensorTimingSeconds;\n}\n\nexport type SensorReadoutTimingDeclaration =\n | GlobalSensorReadoutTimingDeclaration\n | RollingSensorReadoutTimingDeclaration;\n\nexport interface CalculateSensorReadoutTimingInput {\n nativeRaster: NativeImageRaster;\n /**\n * Active capture rectangle, in fixed native pixel coordinates.\n *\n * Defaults to the whole native image. Timing is never worked out by scaling\n * a full-frame value to this rectangle.\n */\n activeCaptureRect?: RasterRect;\n /**\n * The shutter mechanism chosen for the capture.\n *\n * It is reported separately and does not change the sensor readout timing\n * in this model.\n */\n shutterMechanism: CaptureShutterMechanism;\n readout: SensorReadoutTimingDeclaration;\n /**\n * Optional points, in continuous native pixel coordinates measured from pixel\n * edges, to report timing for. A pixel centre is at +0.5.\n */\n samplePointsNative?: readonly RasterPoint[];\n}\n\nexport interface SensorReadoutTimingSample {\n pointNative: RasterPoint;\n normalizedScanPosition: number | null;\n /**\n * Readout time of this point, in seconds, relative to the first scan position (0).\n *\n * It is not automatically an exposure-start time or a shutter-curtain time.\n */\n readoutPhaseOffsetSeconds: number;\n}\n\nexport interface SensorReadoutTiming {\n readoutMode: SensorReadoutMode;\n shutterMechanism: CaptureShutterMechanism;\n nativeRaster: NativeImageRaster;\n activeCaptureRect: RasterRect;\n captureReadoutDurationSeconds: SourcedSensorTimingSeconds;\n maximumSpatialSamplingSkewSeconds: number;\n scan:\n | {\n pattern: \"uniform-linear-single-axis\";\n directionNative: SourcedSensorReadoutFact<NativeSensorReadoutScanDirection>;\n unitVectorNative: { x: number; y: number };\n spatialSamplingSkewSeconds: SourcedSensorTimingSeconds;\n }\n | null;\n samples: readonly SensorReadoutTimingSample[];\n}\n\nconst READOUT_MODES = new Set<SensorReadoutMode>([\"rolling\", \"global\"]);\nconst SCAN_DIRECTIONS = new Set<NativeSensorReadoutScanDirection>([\n \"top-to-bottom\",\n \"bottom-to-top\",\n \"left-to-right\",\n \"right-to-left\"\n]);\nconst SHUTTER_MECHANISMS = new Set<CaptureShutterMechanism>([\n \"mechanical\",\n \"electronic-first-curtain\",\n \"electronic\"\n]);\n\nfunction requireNonNegativeFinite(name: string, value: unknown): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n throw new InvalidScientificInputError(\n name + \" must be a finite number greater than or equal to zero.\"\n );\n }\n return value;\n}\n\nfunction parseSecondsFact(\n value: unknown,\n path: string,\n positive: boolean\n): SourcedSensorTimingSeconds {\n const record = requireRecord(value, path, [\"unit\", \"value\", \"evidence\"]);\n if (record.unit !== \"s\") {\n throw new InvalidConfigurationError(path + '.unit must be \"s\".');\n }\n\n const seconds = positive\n ? requirePositiveFinite(path + \".value\", record.value)\n : requireNonNegativeFinite(path + \".value\", record.value);\n\n return {\n value: seconds,\n unit: \"s\",\n evidence: parseEvidenceList(record.evidence, path + \".evidence\")\n };\n}\n\nfunction parseDirectionFact(\n value: unknown,\n path: string\n): SourcedSensorReadoutFact<NativeSensorReadoutScanDirection> {\n const record = requireRecord(value, path, [\"value\", \"evidence\"]);\n if (\n typeof record.value !== \"string\" ||\n !SCAN_DIRECTIONS.has(\n record.value as NativeSensorReadoutScanDirection\n )\n ) {\n throw new InvalidConfigurationError(path + \".value is invalid.\");\n }\n\n return {\n value: record.value as NativeSensorReadoutScanDirection,\n evidence: parseEvidenceList(record.evidence, path + \".evidence\")\n };\n}\n\nfunction parseReadoutDeclaration(\n value: unknown\n): SensorReadoutTimingDeclaration {\n const record = requireRecord(value, \"readout\", [\"readoutMode\", \"captureReadoutDurationSeconds\", \"scanDirectionNative\", \"spatialSamplingSkewSeconds\"]);\n if (\n typeof record.readoutMode !== \"string\" ||\n !READOUT_MODES.has(record.readoutMode as SensorReadoutMode)\n ) {\n throw new InvalidConfigurationError(\"readout.readoutMode is invalid.\");\n }\n\n const captureReadoutDurationSeconds = parseSecondsFact(\n record.captureReadoutDurationSeconds,\n \"readout.captureReadoutDurationSeconds\",\n false\n );\n\n if (record.readoutMode === \"global\") {\n if (record.scanDirectionNative !== undefined) {\n throw new InvalidScientificInputError(\n \"readout.scanDirectionNative must be omitted for global readout.\"\n );\n }\n if (record.spatialSamplingSkewSeconds !== undefined) {\n throw new InvalidScientificInputError(\n \"readout.spatialSamplingSkewSeconds must be omitted for global readout.\"\n );\n }\n\n return {\n readoutMode: \"global\",\n captureReadoutDurationSeconds\n };\n }\n\n return {\n readoutMode: \"rolling\",\n captureReadoutDurationSeconds,\n scanDirectionNative: parseDirectionFact(\n record.scanDirectionNative,\n \"readout.scanDirectionNative\"\n ),\n spatialSamplingSkewSeconds: parseSecondsFact(\n record.spatialSamplingSkewSeconds,\n \"readout.spatialSamplingSkewSeconds\",\n true\n )\n };\n}\n\nfunction validateActiveCaptureRect(\n rect: RasterRect,\n raster: NativeImageRaster\n): void {\n requireNonNegativeInteger(\"activeCaptureRect.x\", rect.x);\n requireNonNegativeInteger(\"activeCaptureRect.y\", rect.y);\n requirePositiveInteger(\"activeCaptureRect.width\", rect.width);\n requirePositiveInteger(\"activeCaptureRect.height\", rect.height);\n\n if (\n rect.x + rect.width > raster.pixelWidth ||\n rect.y + rect.height > raster.pixelHeight\n ) {\n throw new InvalidScientificInputError(\n \"activeCaptureRect must fit entirely within nativeRaster.\"\n );\n }\n}\n\nfunction validateShutterMechanism(\n value: unknown\n): asserts value is CaptureShutterMechanism {\n if (\n typeof value !== \"string\" ||\n !SHUTTER_MECHANISMS.has(value as CaptureShutterMechanism)\n ) {\n throw new InvalidConfigurationError(\"shutterMechanism is invalid.\");\n }\n}\n\nfunction validatePointWithinActiveCapture(\n point: RasterPoint,\n rect: RasterRect,\n index: number\n): void {\n if (!Number.isFinite(point.x) || !Number.isFinite(point.y)) {\n throw new InvalidScientificInputError(\n \"samplePointsNative[\" + index + \"] coordinates must be finite.\"\n );\n }\n\n if (\n point.x < rect.x ||\n point.x > rect.x + rect.width ||\n point.y < rect.y ||\n point.y > rect.y + rect.height\n ) {\n throw new InvalidScientificInputError(\n \"samplePointsNative[\" +\n index +\n \"] must lie within activeCaptureRect edge-coordinate bounds.\"\n );\n }\n}\n\n/**\n * Resolves the sensor readout scan schedule for one capture.\n *\n * Rolling readout is modelled as a uniform linear scan along one axis of the\n * declared active capture. The caller supplies the scan's time span (skew)\n * explicitly. It is never worked out from the total data-readout time, crop\n * size, pixel density, output resolution, sensor-architecture metadata or the\n * shutter mechanism.\n *\n * Global readout has no skew in this model, even when a non-zero data-readout\n * time is declared.\n *\n * Not covered: local exposure start and end times, mechanical curtain travel,\n * EFCS (electronic first-curtain shutter) behaviour, rolling-shutter image\n * distortion, flash or flicker, and motion integration.\n */\nexport function calculateSensorReadoutTiming(\n input: CalculateSensorReadoutTimingInput\n): CalculationResult<SensorReadoutTiming> {\n requireInputKeys(input, \"calculateSensorReadoutTiming\", [\"nativeRaster\", \"activeCaptureRect\", \"shutterMechanism\", \"readout\", \"samplePointsNative\"]);\n validateNativeRaster(input.nativeRaster);\n validateShutterMechanism(input.shutterMechanism);\n\n const readout = parseReadoutDeclaration(input.readout);\n const activeCaptureRect =\n input.activeCaptureRect ?? fullRect(input.nativeRaster);\n validateActiveCaptureRect(activeCaptureRect, input.nativeRaster);\n\n if (\n input.samplePointsNative !== undefined &&\n !Array.isArray(input.samplePointsNative)\n ) {\n throw new InvalidConfigurationError(\n \"samplePointsNative must be an array when supplied.\"\n );\n }\n\n const scan =\n readout.readoutMode === \"rolling\"\n ? {\n pattern: \"uniform-linear-single-axis\" as const,\n directionNative: readout.scanDirectionNative,\n unitVectorNative: scanVector(readout.scanDirectionNative.value),\n spatialSamplingSkewSeconds: readout.spatialSamplingSkewSeconds\n }\n : null;\n\n const samples = (input.samplePointsNative ?? []).map((point, index) => {\n validatePointWithinActiveCapture(point, activeCaptureRect, index);\n\n if (scan === null) {\n return {\n pointNative: { x: point.x, y: point.y },\n normalizedScanPosition: null,\n readoutPhaseOffsetSeconds: 0\n };\n }\n\n const normalized = normalizedScanPosition(\n point,\n activeCaptureRect,\n scan.directionNative.value\n );\n\n return {\n pointNative: { x: point.x, y: point.y },\n normalizedScanPosition: normalized,\n readoutPhaseOffsetSeconds:\n normalized * scan.spatialSamplingSkewSeconds.value\n };\n });\n\n return approximationResult(\n {\n readoutMode: readout.readoutMode,\n shutterMechanism: input.shutterMechanism,\n nativeRaster: { ...input.nativeRaster },\n activeCaptureRect: { ...activeCaptureRect },\n captureReadoutDurationSeconds:\n readout.captureReadoutDurationSeconds,\n maximumSpatialSamplingSkewSeconds:\n readout.readoutMode === \"rolling\"\n ? readout.spatialSamplingSkewSeconds.value\n : 0,\n scan,\n samples\n },\n \"native-sensor-readout-scan-timing\",\n \"1.0.0\",\n [\n \"Native raster coordinates use top-left origin, +X right and +Y down and remain invariant under physical camera orientation.\",\n \"Rolling timing uses a uniform-linear single-axis approximation over continuous effective native-raster coordinates.\",\n \"NativeImageRaster is an effective image-sampling grid; the timing map does not assert one raster row or column equals one physical photodiode or hardware readout line.\",\n \"Capture data-readout duration and spatial sampling skew are independently declared facts; no equality or ordering relationship is inferred between them.\",\n \"Global readout has zero spatial sampling skew in this model even when capture data-readout duration is non-zero.\",\n \"Active-capture timing is caller-declared and is not inferred by scaling full-frame timing by crop dimensions.\",\n \"Physical orientation and digital output crop/resolution are downstream of this invariant native timing schedule.\",\n \"Shutter mechanism is reported independently and does not alter the sensor scan schedule in this foundation.\",\n \"The model does not represent segmented, center-out, interleaved, multi-tap or other non-uniform readout patterns.\",\n \"The model does not define exposure windows, shutter-curtain travel, rolling-shutter geometry distortion, flash/flicker interaction or camera/subject motion integration.\"\n ]\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"readout-timing.js","sourceRoot":"","sources":["../../src/sensor/readout-timing.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Sensor readout timing: when each position on the sensor is read out during one capture.\n *\n * Rolling readout is modelled as a uniform linear scan along one axis of the declared active capture.\n * The caller supplies the scan's time span (skew) explicitly. It is never worked out from the total\n * data-readout time, the crop size, pixel density, output resolution, sensor-architecture metadata or\n * the shutter mechanism. Global readout has no skew in this model, even when a non-zero data-readout\n * time is declared.\n *\n * Not covered here: local exposure start and end times, mechanical curtain travel, EFCS (electronic\n * first-curtain shutter) behaviour, rolling-shutter image distortion, flash or flicker, and motion\n * integration.\n * @see docs/MOTION_AND_SIGNAL.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport { approximationResult, type CalculationResult } from \"../core/calculation-result.js\";\nimport {\n parseEvidenceList,\n type EvidenceBackedFact\n} from \"../core/evidence-provenance.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport type { RasterPoint, RasterRect } from \"../output/capture-geometry.js\";\nimport type { NativeImageRaster } from \"./sensor-geometry.js\";\nimport type { SensorReadoutArchitecture } from \"./architecture.js\";\nimport { requireInputKeys, requireConfigRecord as requireRecord } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { fullRect } from \"../core/shared-helpers.js\";\nimport { normalizedScanPosition, validateNativeRaster, scanVector, requirePositiveFinite, validateActiveCaptureRect, validateShutterMechanism } from \"./exposure-window.js\";\n\n/**\n * The readout mode chosen for one capture.\n *\n * It uses the same names as the architecture metadata, but does not claim the\n * hardware supports it. SensorArchitectureProfile.readoutCapabilities is\n * descriptive only and is not checked automatically.\n */\nexport type SensorReadoutMode = SensorReadoutArchitecture;\n\nexport type NativeSensorReadoutScanDirection =\n | \"top-to-bottom\"\n | \"bottom-to-top\"\n | \"left-to-right\"\n | \"right-to-left\";\n\nexport type CaptureShutterMechanism =\n | \"mechanical\"\n | \"electronic-first-curtain\"\n | \"electronic\";\n\n/**\n * Evidence-backed timing value with an explicit seconds unit.\n */\nexport interface SourcedSensorTimingSeconds\n extends EvidenceBackedFact<number> {\n unit: \"s\";\n}\n\nexport type SourcedSensorReadoutFact<T> = EvidenceBackedFact<T>;\n\nexport interface GlobalSensorReadoutTimingDeclaration {\n readoutMode: \"global\";\n /**\n * Sensor data-readout time for this capture.\n *\n * It is deliberately not treated as the spatial exposure or readout skew.\n */\n captureReadoutDurationSeconds: SourcedSensorTimingSeconds;\n scanDirectionNative?: never;\n spatialSamplingSkewSeconds?: never;\n}\n\nexport interface RollingSensorReadoutTimingDeclaration {\n readoutMode: \"rolling\";\n /**\n * Sensor data-readout time for this capture.\n *\n * It is kept separate from the spatial skew, because a published readout time\n * and the scan's time span are not necessarily the same quantity.\n */\n captureReadoutDurationSeconds: SourcedSensorTimingSeconds;\n /**\n * Native-sensor scan direction for the selected capture mode.\n */\n scanDirectionNative: SourcedSensorReadoutFact<NativeSensorReadoutScanDirection>;\n /**\n * Time between the first and last scan positions, in the uniform linear\n * timing approximation (the readout skew).\n */\n spatialSamplingSkewSeconds: SourcedSensorTimingSeconds;\n}\n\nexport type SensorReadoutTimingDeclaration =\n | GlobalSensorReadoutTimingDeclaration\n | RollingSensorReadoutTimingDeclaration;\n\nexport interface CalculateSensorReadoutTimingInput {\n nativeRaster: NativeImageRaster;\n /**\n * Active capture rectangle, in fixed native pixel coordinates.\n *\n * Defaults to the whole native image. Timing is never worked out by scaling\n * a full-frame value to this rectangle.\n */\n activeCaptureRect?: RasterRect;\n /**\n * The shutter mechanism chosen for the capture.\n *\n * It is reported separately and does not change the sensor readout timing\n * in this model.\n */\n shutterMechanism: CaptureShutterMechanism;\n readout: SensorReadoutTimingDeclaration;\n /**\n * Optional points, in continuous native pixel coordinates measured from pixel\n * edges, to report timing for. A pixel centre is at +0.5.\n */\n samplePointsNative?: readonly RasterPoint[];\n}\n\nexport interface SensorReadoutTimingSample {\n pointNative: RasterPoint;\n normalizedScanPosition: number | null;\n /**\n * Readout time of this point, in seconds, relative to the first scan position (0).\n *\n * It is not automatically an exposure-start time or a shutter-curtain time.\n */\n readoutPhaseOffsetSeconds: number;\n}\n\nexport interface SensorReadoutTiming {\n readoutMode: SensorReadoutMode;\n shutterMechanism: CaptureShutterMechanism;\n nativeRaster: NativeImageRaster;\n activeCaptureRect: RasterRect;\n captureReadoutDurationSeconds: SourcedSensorTimingSeconds;\n maximumSpatialSamplingSkewSeconds: number;\n scan:\n | {\n pattern: \"uniform-linear-single-axis\";\n directionNative: SourcedSensorReadoutFact<NativeSensorReadoutScanDirection>;\n unitVectorNative: { x: number; y: number };\n spatialSamplingSkewSeconds: SourcedSensorTimingSeconds;\n }\n | null;\n samples: readonly SensorReadoutTimingSample[];\n}\n\nconst READOUT_MODES = new Set<SensorReadoutMode>([\"rolling\", \"global\"]);\nconst SCAN_DIRECTIONS = new Set<NativeSensorReadoutScanDirection>([\n \"top-to-bottom\",\n \"bottom-to-top\",\n \"left-to-right\",\n \"right-to-left\"\n]);\n\nfunction requireNonNegativeFinite(name: string, value: unknown): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n throw new InvalidScientificInputError(\n name + \" must be a finite number greater than or equal to zero.\"\n );\n }\n return value;\n}\n\nfunction parseSecondsFact(\n value: unknown,\n path: string,\n positive: boolean\n): SourcedSensorTimingSeconds {\n const record = requireRecord(value, path, [\"unit\", \"value\", \"evidence\"]);\n if (record.unit !== \"s\") {\n throw new InvalidConfigurationError(path + '.unit must be \"s\".');\n }\n\n const seconds = positive\n ? requirePositiveFinite(path + \".value\", record.value)\n : requireNonNegativeFinite(path + \".value\", record.value);\n\n return {\n value: seconds,\n unit: \"s\",\n evidence: parseEvidenceList(record.evidence, path + \".evidence\")\n };\n}\n\nfunction parseDirectionFact(\n value: unknown,\n path: string\n): SourcedSensorReadoutFact<NativeSensorReadoutScanDirection> {\n const record = requireRecord(value, path, [\"value\", \"evidence\"]);\n if (\n typeof record.value !== \"string\" ||\n !SCAN_DIRECTIONS.has(\n record.value as NativeSensorReadoutScanDirection\n )\n ) {\n throw new InvalidConfigurationError(path + \".value is invalid.\");\n }\n\n return {\n value: record.value as NativeSensorReadoutScanDirection,\n evidence: parseEvidenceList(record.evidence, path + \".evidence\")\n };\n}\n\nfunction parseReadoutDeclaration(\n value: unknown\n): SensorReadoutTimingDeclaration {\n const record = requireRecord(value, \"readout\", [\"readoutMode\", \"captureReadoutDurationSeconds\", \"scanDirectionNative\", \"spatialSamplingSkewSeconds\"]);\n if (\n typeof record.readoutMode !== \"string\" ||\n !READOUT_MODES.has(record.readoutMode as SensorReadoutMode)\n ) {\n throw new InvalidConfigurationError(\"readout.readoutMode is invalid.\");\n }\n\n const captureReadoutDurationSeconds = parseSecondsFact(\n record.captureReadoutDurationSeconds,\n \"readout.captureReadoutDurationSeconds\",\n false\n );\n\n if (record.readoutMode === \"global\") {\n if (record.scanDirectionNative !== undefined) {\n throw new InvalidScientificInputError(\n \"readout.scanDirectionNative must be omitted for global readout.\"\n );\n }\n if (record.spatialSamplingSkewSeconds !== undefined) {\n throw new InvalidScientificInputError(\n \"readout.spatialSamplingSkewSeconds must be omitted for global readout.\"\n );\n }\n\n return {\n readoutMode: \"global\",\n captureReadoutDurationSeconds\n };\n }\n\n return {\n readoutMode: \"rolling\",\n captureReadoutDurationSeconds,\n scanDirectionNative: parseDirectionFact(\n record.scanDirectionNative,\n \"readout.scanDirectionNative\"\n ),\n spatialSamplingSkewSeconds: parseSecondsFact(\n record.spatialSamplingSkewSeconds,\n \"readout.spatialSamplingSkewSeconds\",\n true\n )\n };\n}\n\n\n\nfunction validatePointWithinActiveCapture(\n point: RasterPoint,\n rect: RasterRect,\n index: number\n): void {\n if (!Number.isFinite(point.x) || !Number.isFinite(point.y)) {\n throw new InvalidScientificInputError(\n \"samplePointsNative[\" + index + \"] coordinates must be finite.\"\n );\n }\n\n if (\n point.x < rect.x ||\n point.x > rect.x + rect.width ||\n point.y < rect.y ||\n point.y > rect.y + rect.height\n ) {\n throw new InvalidScientificInputError(\n \"samplePointsNative[\" +\n index +\n \"] must lie within activeCaptureRect edge-coordinate bounds.\"\n );\n }\n}\n\n/**\n * Resolves the sensor readout scan schedule for one capture.\n *\n * Rolling readout is modelled as a uniform linear scan along one axis of the\n * declared active capture. The caller supplies the scan's time span (skew)\n * explicitly. It is never worked out from the total data-readout time, crop\n * size, pixel density, output resolution, sensor-architecture metadata or the\n * shutter mechanism.\n *\n * Global readout has no skew in this model, even when a non-zero data-readout\n * time is declared.\n *\n * Not covered: local exposure start and end times, mechanical curtain travel,\n * EFCS (electronic first-curtain shutter) behaviour, rolling-shutter image\n * distortion, flash or flicker, and motion integration.\n */\nexport function calculateSensorReadoutTiming(\n input: CalculateSensorReadoutTimingInput\n): CalculationResult<SensorReadoutTiming> {\n requireInputKeys(input, \"calculateSensorReadoutTiming\", [\"nativeRaster\", \"activeCaptureRect\", \"shutterMechanism\", \"readout\", \"samplePointsNative\"]);\n validateNativeRaster(input.nativeRaster);\n validateShutterMechanism(input.shutterMechanism);\n\n const readout = parseReadoutDeclaration(input.readout);\n const activeCaptureRect =\n input.activeCaptureRect ?? fullRect(input.nativeRaster);\n validateActiveCaptureRect(activeCaptureRect, input.nativeRaster);\n\n if (\n input.samplePointsNative !== undefined &&\n !Array.isArray(input.samplePointsNative)\n ) {\n throw new InvalidConfigurationError(\n \"samplePointsNative must be an array when supplied.\"\n );\n }\n\n const scan =\n readout.readoutMode === \"rolling\"\n ? {\n pattern: \"uniform-linear-single-axis\" as const,\n directionNative: readout.scanDirectionNative,\n unitVectorNative: scanVector(readout.scanDirectionNative.value),\n spatialSamplingSkewSeconds: readout.spatialSamplingSkewSeconds\n }\n : null;\n\n const samples = (input.samplePointsNative ?? []).map((point, index) => {\n validatePointWithinActiveCapture(point, activeCaptureRect, index);\n\n if (scan === null) {\n return {\n pointNative: { x: point.x, y: point.y },\n normalizedScanPosition: null,\n readoutPhaseOffsetSeconds: 0\n };\n }\n\n const normalized = normalizedScanPosition(\n point,\n activeCaptureRect,\n scan.directionNative.value\n );\n\n return {\n pointNative: { x: point.x, y: point.y },\n normalizedScanPosition: normalized,\n readoutPhaseOffsetSeconds:\n normalized * scan.spatialSamplingSkewSeconds.value\n };\n });\n\n return approximationResult(\n {\n readoutMode: readout.readoutMode,\n shutterMechanism: input.shutterMechanism,\n nativeRaster: { ...input.nativeRaster },\n activeCaptureRect: { ...activeCaptureRect },\n captureReadoutDurationSeconds:\n readout.captureReadoutDurationSeconds,\n maximumSpatialSamplingSkewSeconds:\n readout.readoutMode === \"rolling\"\n ? readout.spatialSamplingSkewSeconds.value\n : 0,\n scan,\n samples\n },\n \"native-sensor-readout-scan-timing\",\n \"1.0.0\",\n [\n \"Native raster coordinates use top-left origin, +X right and +Y down and remain invariant under physical camera orientation.\",\n \"Rolling timing uses a uniform-linear single-axis approximation over continuous effective native-raster coordinates.\",\n \"NativeImageRaster is an effective image-sampling grid; the timing map does not assert one raster row or column equals one physical photodiode or hardware readout line.\",\n \"Capture data-readout duration and spatial sampling skew are independently declared facts; no equality or ordering relationship is inferred between them.\",\n \"Global readout has zero spatial sampling skew in this model even when capture data-readout duration is non-zero.\",\n \"Active-capture timing is caller-declared and is not inferred by scaling full-frame timing by crop dimensions.\",\n \"Physical orientation and digital output crop/resolution are downstream of this invariant native timing schedule.\",\n \"Shutter mechanism is reported independently and does not alter the sensor scan schedule in this foundation.\",\n \"The model does not represent segmented, center-out, interleaved, multi-tap or other non-uniform readout patterns.\",\n \"The model does not define exposure windows, shutter-curtain travel, rolling-shutter geometry distortion, flash/flicker interaction or camera/subject motion integration.\"\n ]\n );\n}\n"]}
|
|
@@ -15,7 +15,7 @@ import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
|
15
15
|
import { parseEvidenceList } from "../core/evidence-provenance.js";
|
|
16
16
|
import { InvalidScientificInputError } from "../core/validation.js";
|
|
17
17
|
import { requireInputObject, requireInputKeys, rejectUnknownVariantFields, requireConfigRecord as requireRecord, requireConfigString as requireNonEmptyString, requireConfigPositiveFinite as requirePositiveFinite } from "../core/record-validation.js";
|
|
18
|
-
|
|
18
|
+
import { approximatelyEqual } from "../core/shared-helpers.js";
|
|
19
19
|
function parseIncidentAreaBasis(value, path) {
|
|
20
20
|
const record = requireRecord(value, path, ["areaSquareMicrometers", "kind"]);
|
|
21
21
|
const areaSquareMicrometers = requirePositiveFinite(record.areaSquareMicrometers, path + ".areaSquareMicrometers");
|
|
@@ -135,11 +135,6 @@ function requiredSourcePlane(scope) {
|
|
|
135
135
|
? "sensor-package-incident"
|
|
136
136
|
: "site-incident";
|
|
137
137
|
}
|
|
138
|
-
function approximatelyEqual(actual, expected) {
|
|
139
|
-
const scale = Math.max(1, Math.abs(actual), Math.abs(expected));
|
|
140
|
-
return (Math.abs(actual - expected) <=
|
|
141
|
-
AREA_TOLERANCE * scale);
|
|
142
|
-
}
|
|
143
138
|
export function conditionsMatch(reference, operating) {
|
|
144
139
|
if (reference.temperatureC !==
|
|
145
140
|
undefined &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-application-compatibility.js","sourceRoot":"","sources":["../../src/sensor/response-application-compatibility.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Response application compatibility: checks that a measured sensor response can be applied to this\n * light input.\n *\n * It checks the exact profile and channel, the plane where the input light is measured (source\n * plane), the area the response refers to, spatial uniformity and the reference conditions of the\n * measurement. Passing this check alone does not allow converting light to signal. The per-bin\n * operating-range check and the EQE or A/W conversion are separate steps.\n * @see docs/MOTION_AND_SIGNAL.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport {\n calculatedResult,\n type CalculationResult\n} from \"../core/calculation-result.js\";\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 SensorSpectralReferenceConditions,\n SensorSpectralResponseScientificStatus\n} from \"./spectral-response.js\";\nimport type {\n SensorSpatioSpectralIrradianceReduction\n} from \"./spatio-spectral-reduction.js\";\nimport { requireInputObject, requireInputKeys, rejectUnknownVariantFields, requireConfigRecord as requireRecord, requireConfigString as requireNonEmptyString, requireConfigPositiveFinite as requirePositiveFinite } from \"../core/record-validation.js\";\n\nconst AREA_TOLERANCE = 1e-10;\n\nexport type SensorResponseSourcePlane =\n | \"sensor-package-incident\"\n | \"site-incident\";\n\nexport type SensorResponseIncidentAreaBasis =\n | {\n kind: \"geometric-sensitive-aperture\";\n areaSquareMicrometers: number;\n }\n | {\n kind: \"full-site-cell\";\n areaSquareMicrometers: number;\n }\n | {\n kind: \"effective-collection-area\";\n areaSquareMicrometers: number;\n };\n\nexport type SensorResponseSpatialModel =\n | {\n kind:\n \"uniform-over-geometric-sensitive-aperture\";\n scientificStatus:\n SensorSpectralResponseScientificStatus;\n evidence: readonly EvidenceProvenance[];\n limitation?: string;\n }\n | {\n kind: \"not-established\";\n limitation: string;\n };\n\nexport type SensorResponseReferenceConditionPolicy =\n | {\n kind: \"exact-match-required\";\n }\n | {\n kind: \"assume-compatible\";\n limitation: string;\n evidence: readonly EvidenceProvenance[];\n };\n\nexport interface SensorResponseApplicationProfile {\n schemaVersion: \"0.1.0\";\n profileId: string;\n spectralResponseProfileId: string;\n colorSamplingProfileId: string;\n channelId: string;\n samplingApertureProfileId: string;\n opticalStackProfileId: string;\n evidence: readonly EvidenceProvenance[];\n incidentAreaBasis:\n SensorResponseIncidentAreaBasis;\n spatialResponseModel:\n SensorResponseSpatialModel;\n referenceConditionPolicy:\n SensorResponseReferenceConditionPolicy;\n}\n\nexport interface SourcedSensorResponseSourcePlane {\n value: SensorResponseSourcePlane;\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface AssessSensorResponseApplicationCompatibilityInput {\n reduction:\n SensorSpatioSpectralIrradianceReduction;\n applicationProfile:\n SensorResponseApplicationProfile;\n sourcePlane:\n SourcedSensorResponseSourcePlane;\n operatingConditions?:\n SensorSpectralReferenceConditions;\n}\n\nexport type SensorResponseApplicationCompatibilityBlocker =\n | \"spectral-response-profile-id-mismatch\"\n | \"color-sampling-profile-id-mismatch\"\n | \"channel-id-mismatch\"\n | \"sampling-aperture-profile-id-missing\"\n | \"sampling-aperture-profile-id-mismatch\"\n | \"optical-stack-profile-id-missing\"\n | \"optical-stack-profile-id-mismatch\"\n | \"source-plane-mismatch\"\n | \"wavelength-basis-unresolved\"\n | \"incident-area-basis-not-currently-integrated\"\n | \"incident-area-mismatch\"\n | \"spatial-response-uniformity-not-established\"\n | \"response-reference-conditions-not-declared\"\n | \"operating-conditions-not-declared\"\n | \"operating-conditions-mismatch\";\n\nexport type SensorResponseSignalPath =\n | \"photon-rate-to-electrons\"\n | \"radiant-power-to-current\";\n\nexport interface SensorResponseApplicationCompatibilityAssessment {\n applicationProfileId: string;\n spectralResponseProfileId: string;\n colorSamplingProfileId: string;\n channelId: string;\n responseScope:\n SensorSpatioSpectralIrradianceReduction[\"responseScope\"];\n requiredSourcePlane:\n SensorResponseSourcePlane;\n suppliedSourcePlane:\n SensorResponseSourcePlane;\n sourcePlaneMatched: boolean;\n responseIncidentAreaBasis:\n SensorResponseIncidentAreaBasis;\n currentlyIntegratedAreaBasis:\n \"geometric-sensitive-aperture\";\n geometricApertureAreaSquareMicrometers:\n number;\n nominalSiteCellAreaSquareMicrometers?:\n number;\n spatialResponseModel:\n SensorResponseSpatialModel;\n referenceConditionPolicy:\n SensorResponseReferenceConditionPolicy;\n responseReferenceConditions?:\n SensorSpectralReferenceConditions;\n operatingConditions?:\n SensorSpectralReferenceConditions;\n structuralCompatibilityEstablished:\n boolean;\n compatibilityStatus:\n | \"compatible\"\n | \"compatible-approximation\"\n | \"blocked\";\n blockers:\n readonly SensorResponseApplicationCompatibilityBlocker[];\n requiredSignalPath:\n SensorResponseSignalPath;\n quantifiedResponseUncertaintyAvailable:\n boolean;\n responseApplicationPerformed: false;\n signalConversionAuthorized: false;\n temporalIntegrationAuthorized: false;\n photonConversionPerformed: false;\n electronConversionPerformed: false;\n currentConversionPerformed: false;\n operatingRangeCompatibilityAssessed: false;\n spatiallyVaryingResponseSupported: false;\n componentEvidence: {\n applicationProfile:\n readonly EvidenceProvenance[];\n sourcePlane:\n readonly EvidenceProvenance[];\n spatialResponse:\n readonly EvidenceProvenance[];\n referenceConditionAssumption:\n readonly EvidenceProvenance[];\n response:\n SensorSpatioSpectralIrradianceReduction[\"componentEvidence\"][\"spectral\"];\n };\n}\n\nfunction parseIncidentAreaBasis(\n value: unknown,\n path: string\n): SensorResponseIncidentAreaBasis {\n const record =\n requireRecord(value, path, [\"areaSquareMicrometers\", \"kind\"]);\n const areaSquareMicrometers =\n requirePositiveFinite(\n record.areaSquareMicrometers,\n path + \".areaSquareMicrometers\"\n );\n\n if (\n record.kind !==\n \"geometric-sensitive-aperture\" &&\n record.kind !== \"full-site-cell\" &&\n record.kind !==\n \"effective-collection-area\"\n ) {\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n }\n\n return {\n kind: record.kind,\n areaSquareMicrometers\n };\n}\n\nfunction parseSpatialResponseModel(\n value: unknown,\n path: string\n): SensorResponseSpatialModel {\n const record =\n requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", { \"not-established\": [\"kind\", \"limitation\"], \"uniform-over-geometric-sensitive-aperture\": [\"kind\", \"scientificStatus\", \"evidence\", \"limitation\"] }, path);\n\n if (\n record.kind === \"not-established\"\n ) {\n return {\n kind: \"not-established\",\n limitation: requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n if (\n record.kind !==\n \"uniform-over-geometric-sensitive-aperture\"\n ) {\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n }\n\n if (\n record.scientificStatus !==\n \"calibrated\" &&\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \".scientificStatus is invalid.\"\n );\n }\n\n const limitation =\n record.limitation === undefined\n ? undefined\n : requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n );\n\n if (\n record.scientificStatus ===\n \"approximation\" &&\n limitation === undefined\n ) {\n throw new InvalidConfigurationError(\n path +\n \".limitation is required for an approximation.\"\n );\n }\n\n return {\n kind:\n \"uniform-over-geometric-sensitive-aperture\",\n scientificStatus:\n record.scientificStatus,\n evidence: parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n ),\n ...(limitation === undefined\n ? {}\n : { limitation })\n };\n}\n\nexport function parseReferenceConditionPolicy(\n value: unknown,\n path: string\n): SensorResponseReferenceConditionPolicy {\n const record =\n requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", { \"exact-match-required\": [\"kind\"], \"assume-compatible\": [\"kind\", \"limitation\", \"evidence\"] }, path);\n\n if (\n record.kind ===\n \"exact-match-required\"\n ) {\n return {\n kind: \"exact-match-required\"\n };\n }\n\n if (\n record.kind === \"assume-compatible\"\n ) {\n return {\n kind: \"assume-compatible\",\n limitation: requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n ),\n evidence: parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\n/**\n * Validates untrusted input and returns it as a normalized, typed value. Unknown enum values,\n * missing required fields and inconsistent scientific data are rejected.\n *\n * The profile states the source plane, incident-area basis, spatial uniformity and reference\n * conditions under which a response applies.\n * @param value - Untrusted data. TypeScript types alone are not validation.\n * @returns The result. Success does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the package export and its full type definitions.\n */\nexport function parseSensorResponseApplicationProfile(\n value: unknown\n): SensorResponseApplicationProfile {\n const record = requireRecord(\n value,\n \"sensorResponseApplication\", [\"schemaVersion\", \"profileId\", \"spectralResponseProfileId\", \"colorSamplingProfileId\", \"channelId\", \"samplingApertureProfileId\", \"opticalStackProfileId\", \"evidence\", \"incidentAreaBasis\", \"spatialResponseModel\", \"referenceConditionPolicy\"]\n );\n\n if (\n record.schemaVersion !== \"0.1.0\"\n ) {\n throw new InvalidConfigurationError(\n 'sensorResponseApplication.schemaVersion must be \"0.1.0\".'\n );\n }\n\n return {\n schemaVersion: \"0.1.0\",\n profileId: requireNonEmptyString(\n record.profileId,\n \"sensorResponseApplication.profileId\"\n ),\n spectralResponseProfileId:\n requireNonEmptyString(\n record.spectralResponseProfileId,\n \"sensorResponseApplication.spectralResponseProfileId\"\n ),\n colorSamplingProfileId:\n requireNonEmptyString(\n record.colorSamplingProfileId,\n \"sensorResponseApplication.colorSamplingProfileId\"\n ),\n channelId: requireNonEmptyString(\n record.channelId,\n \"sensorResponseApplication.channelId\"\n ),\n samplingApertureProfileId:\n requireNonEmptyString(\n record.samplingApertureProfileId,\n \"sensorResponseApplication.samplingApertureProfileId\"\n ),\n opticalStackProfileId:\n requireNonEmptyString(\n record.opticalStackProfileId,\n \"sensorResponseApplication.opticalStackProfileId\"\n ),\n evidence: parseEvidenceList(\n record.evidence,\n \"sensorResponseApplication.evidence\"\n ),\n incidentAreaBasis:\n parseIncidentAreaBasis(\n record.incidentAreaBasis,\n \"sensorResponseApplication.incidentAreaBasis\"\n ),\n spatialResponseModel:\n parseSpatialResponseModel(\n record.spatialResponseModel,\n \"sensorResponseApplication.spatialResponseModel\"\n ),\n referenceConditionPolicy:\n parseReferenceConditionPolicy(\n record.referenceConditionPolicy,\n \"sensorResponseApplication.referenceConditionPolicy\"\n )\n };\n}\n\nfunction parseSourcePlane(\n value:\n SourcedSensorResponseSourcePlane\n): SourcedSensorResponseSourcePlane {\n const record = requireRecord(\n value,\n \"sourcePlane\", [\"value\", \"evidence\"]\n );\n if (\n record.value !==\n \"sensor-package-incident\" &&\n record.value !== \"site-incident\"\n ) {\n throw new InvalidConfigurationError(\n \"sourcePlane.value is invalid.\"\n );\n }\n return {\n value: record.value,\n evidence: parseEvidenceList(\n record.evidence,\n \"sourcePlane.evidence\"\n )\n };\n}\n\nfunction requiredSourcePlane(\n scope:\n SensorSpatioSpectralIrradianceReduction[\"responseScope\"]\n): SensorResponseSourcePlane {\n return scope ===\n \"sensor-package-incident-effective-channel-response\"\n ? \"sensor-package-incident\"\n : \"site-incident\";\n}\n\nfunction approximatelyEqual(\n actual: number,\n expected: number\n): boolean {\n const scale = Math.max(\n 1,\n Math.abs(actual),\n Math.abs(expected)\n );\n return (\n Math.abs(actual - expected) <=\n AREA_TOLERANCE * scale\n );\n}\n\nexport function conditionsMatch(\n reference:\n SensorSpectralReferenceConditions,\n operating:\n SensorSpectralReferenceConditions\n): boolean {\n if (\n reference.temperatureC !==\n undefined &&\n operating.temperatureC !==\n reference.temperatureC\n ) {\n return false;\n }\n if (\n reference\n .incidenceAngleDegreesFromNormal !==\n undefined &&\n operating\n .incidenceAngleDegreesFromNormal !==\n reference\n .incidenceAngleDegreesFromNormal\n ) {\n return false;\n }\n if (\n reference.polarization !==\n undefined &&\n operating.polarization !==\n reference.polarization\n ) {\n return false;\n }\n return true;\n}\n\nfunction validateReductionBoundary(\n reduction:\n SensorSpatioSpectralIrradianceReduction\n): number {\n requireInputObject(reduction, \"reduction input\");\n if (\n reduction.outputMeaning !==\n \"pre-response-spatio-spectral-radiometric-reduction\" ||\n reduction\n .spectralResponseApplicationPerformed !==\n false ||\n reduction.quantumEfficiencyApplied !==\n false ||\n reduction.spectralResponsivityApplied !==\n false ||\n reduction.temporalIntegrationApplied !==\n false\n ) {\n throw new InvalidScientificInputError(\n \"reduction must remain a pre-response, pre-temporal spatio-spectral result.\"\n );\n }\n\n if (\n typeof reduction\n .geometricApertureAreaSquareMicrometers !==\n \"number\" ||\n !Number.isFinite(\n reduction\n .geometricApertureAreaSquareMicrometers\n ) ||\n reduction\n .geometricApertureAreaSquareMicrometers <=\n 0\n ) {\n throw new InvalidScientificInputError(\n \"reduction.geometricApertureAreaSquareMicrometers is required and must be positive.\"\n );\n }\n\n return reduction\n .geometricApertureAreaSquareMicrometers;\n}\n\n/**\n * Checks whether the source plane, area, profile, channel and reference conditions allow the\n * selected way of applying the response.\n *\n * Passing this alone does not allow converting light to signal. The per-bin operating-range check\n * and the EQE or A/W conversion are separate steps.\n * @param input - The input; see `AssessSensorResponseApplicationCompatibilityInput` for its fields, units and coordinates.\n * @returns The assessment. Read its structured blockers before acting on an authorization.\n *\n * @see docs/API_REFERENCE.md for the package export and its full type definitions.\n */\nexport function assessSensorResponseApplicationCompatibility(\n input:\n AssessSensorResponseApplicationCompatibilityInput\n): CalculationResult<SensorResponseApplicationCompatibilityAssessment> {\n requireInputKeys(input, \"assessSensorResponseApplicationCompatibility\", [\"reduction\", \"applicationProfile\", \"sourcePlane\", \"operatingConditions\"]);\n const geometricArea =\n validateReductionBoundary(\n input.reduction\n );\n const profile =\n parseSensorResponseApplicationProfile(\n input.applicationProfile\n );\n const sourcePlane =\n parseSourcePlane(input.sourcePlane);\n const blockers:\n SensorResponseApplicationCompatibilityBlocker[] =\n [];\n\n if (\n profile.spectralResponseProfileId !==\n input.reduction.responseProfileId\n ) {\n blockers.push(\n \"spectral-response-profile-id-mismatch\"\n );\n }\n if (\n profile.colorSamplingProfileId !==\n input.reduction\n .colorSamplingProfileId\n ) {\n blockers.push(\n \"color-sampling-profile-id-mismatch\"\n );\n }\n if (\n profile.channelId !==\n input.reduction.channelId\n ) {\n blockers.push(\n \"channel-id-mismatch\"\n );\n }\n\n const samplingApertureProfileId =\n input.reduction\n .samplingApertureProfileId;\n if (\n samplingApertureProfileId ===\n undefined\n ) {\n blockers.push(\n \"sampling-aperture-profile-id-missing\"\n );\n } else if (\n samplingApertureProfileId !==\n profile.samplingApertureProfileId\n ) {\n blockers.push(\n \"sampling-aperture-profile-id-mismatch\"\n );\n }\n\n const opticalStackProfileId =\n input.reduction\n .opticalStackProfileId;\n if (\n opticalStackProfileId === undefined\n ) {\n blockers.push(\n \"optical-stack-profile-id-missing\"\n );\n } else if (\n opticalStackProfileId !==\n profile.opticalStackProfileId\n ) {\n blockers.push(\n \"optical-stack-profile-id-mismatch\"\n );\n }\n\n const requiredPlane =\n requiredSourcePlane(\n input.reduction.responseScope\n );\n const sourcePlaneMatched =\n sourcePlane.value === requiredPlane;\n if (!sourcePlaneMatched) {\n blockers.push(\n \"source-plane-mismatch\"\n );\n }\n\n if (\n !input.reduction\n .wavelengthBasisResolved\n ) {\n blockers.push(\n \"wavelength-basis-unresolved\"\n );\n }\n\n if (\n profile.incidentAreaBasis.kind !==\n \"geometric-sensitive-aperture\"\n ) {\n blockers.push(\n \"incident-area-basis-not-currently-integrated\"\n );\n } else if (\n !approximatelyEqual(\n profile.incidentAreaBasis\n .areaSquareMicrometers,\n geometricArea\n )\n ) {\n blockers.push(\n \"incident-area-mismatch\"\n );\n }\n\n if (\n profile.spatialResponseModel.kind ===\n \"not-established\"\n ) {\n blockers.push(\n \"spatial-response-uniformity-not-established\"\n );\n }\n\n if (\n profile.referenceConditionPolicy.kind ===\n \"exact-match-required\"\n ) {\n const referenceConditions =\n input.reduction\n .responseReferenceConditions;\n if (\n referenceConditions === undefined\n ) {\n blockers.push(\n \"response-reference-conditions-not-declared\"\n );\n } else if (\n input.operatingConditions ===\n undefined\n ) {\n blockers.push(\n \"operating-conditions-not-declared\"\n );\n } else if (\n !conditionsMatch(\n referenceConditions,\n input.operatingConditions\n )\n ) {\n blockers.push(\n \"operating-conditions-mismatch\"\n );\n }\n }\n\n const structurallyCompatible =\n blockers.length === 0;\n\n const approximation =\n input.reduction\n .responseScientificStatus ===\n \"approximation\" ||\n (\n profile.spatialResponseModel.kind ===\n \"uniform-over-geometric-sensitive-aperture\" &&\n profile.spatialResponseModel\n .scientificStatus ===\n \"approximation\"\n ) ||\n profile.referenceConditionPolicy.kind ===\n \"assume-compatible\";\n\n const compatibilityStatus =\n structurallyCompatible\n ? approximation\n ? \"compatible-approximation\"\n : \"compatible\"\n : \"blocked\";\n\n const spatialEvidence =\n profile.spatialResponseModel.kind ===\n \"uniform-over-geometric-sensitive-aperture\"\n ? profile.spatialResponseModel.evidence\n : [];\n const referenceConditionEvidence =\n profile.referenceConditionPolicy.kind ===\n \"assume-compatible\"\n ? profile.referenceConditionPolicy\n .evidence\n : [];\n\n return calculatedResult(\n {\n applicationProfileId:\n profile.profileId,\n spectralResponseProfileId:\n input.reduction\n .responseProfileId,\n colorSamplingProfileId:\n input.reduction\n .colorSamplingProfileId,\n channelId:\n input.reduction.channelId,\n responseScope:\n input.reduction.responseScope,\n requiredSourcePlane:\n requiredPlane,\n suppliedSourcePlane:\n sourcePlane.value,\n sourcePlaneMatched,\n responseIncidentAreaBasis:\n profile.incidentAreaBasis,\n currentlyIntegratedAreaBasis:\n \"geometric-sensitive-aperture\",\n geometricApertureAreaSquareMicrometers:\n geometricArea,\n ...(input.reduction\n .nominalSiteCellAreaSquareMicrometers ===\n undefined\n ? {}\n : {\n nominalSiteCellAreaSquareMicrometers:\n input.reduction\n .nominalSiteCellAreaSquareMicrometers\n }),\n spatialResponseModel:\n profile.spatialResponseModel,\n referenceConditionPolicy:\n profile.referenceConditionPolicy,\n ...(input.reduction\n .responseReferenceConditions ===\n undefined\n ? {}\n : {\n responseReferenceConditions:\n input.reduction\n .responseReferenceConditions\n }),\n ...(input.operatingConditions ===\n undefined\n ? {}\n : {\n operatingConditions:\n input.operatingConditions\n }),\n structuralCompatibilityEstablished:\n structurallyCompatible,\n compatibilityStatus,\n blockers,\n requiredSignalPath:\n input.reduction\n .sourceResponseKind ===\n \"effective-spectral-responsivity\"\n ? \"radiant-power-to-current\"\n : \"photon-rate-to-electrons\",\n quantifiedResponseUncertaintyAvailable:\n input.reduction\n .responseUncertainty.kind ===\n \"relative\",\n responseApplicationPerformed:\n false,\n signalConversionAuthorized:\n false,\n temporalIntegrationAuthorized:\n false,\n photonConversionPerformed:\n false,\n electronConversionPerformed:\n false,\n currentConversionPerformed:\n false,\n operatingRangeCompatibilityAssessed:\n false,\n spatiallyVaryingResponseSupported:\n false,\n componentEvidence: {\n applicationProfile:\n profile.evidence,\n sourcePlane:\n sourcePlane.evidence,\n spatialResponse:\n spatialEvidence,\n referenceConditionAssumption:\n referenceConditionEvidence,\n response:\n input.reduction\n .componentEvidence.spectral\n }\n },\n \"sensor-response-application-compatibility\",\n \"1.0.0\",\n [\n \"This result is a structural compatibility gate only; it never authorizes or performs sensor-response signal conversion.\",\n \"Response reference plane is derived from responseScope. Package-incident and site-incident inputs are not interchangeable.\",\n \"The current spatio-spectral reducer integrates the geometric sensitive aperture only. Full-site-cell and effective-collection-area response normalizations remain blocked until matching radiometric integrations exist.\",\n \"A scalar wavelength-only response may be applied after spatial reduction only when uniform/separable response over the integrated geometric aperture is explicitly established or declared as an approximation.\",\n \"Exact reference-condition matching is required when that policy is selected because temperature, incidence-angle and polarization dependence are not modeled.\",\n \"An unresolved wavelength basis is incompatible with physical response application.\",\n \"Typical total-pixel QE definitions can include fill factor and microlens effects; they must not be applied to geometric-sensitive-aperture flux unless the response normalization explicitly matches that area basis.\",\n \"Response linearity/dynamic-range validity is not assessed by this gate and remains required before a future conversion can claim calibrated applicability.\",\n \"EQE/filter×EQE responses require a future photon-rate→electron path; A/W responsivity requires a separate radiant-power→current path.\",\n \"Temporal integration, photons/electrons/current, noise, saturation, ADC/RAW conversion and reconstruction remain downstream.\"\n ]\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"response-application-compatibility.js","sourceRoot":"","sources":["../../src/sensor/response-application-compatibility.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Response application compatibility: checks that a measured sensor response can be applied to this\n * light input.\n *\n * It checks the exact profile and channel, the plane where the input light is measured (source\n * plane), the area the response refers to, spatial uniformity and the reference conditions of the\n * measurement. Passing this check alone does not allow converting light to signal. The per-bin\n * operating-range check and the EQE or A/W conversion are separate steps.\n * @see docs/MOTION_AND_SIGNAL.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport {\n calculatedResult,\n type CalculationResult\n} from \"../core/calculation-result.js\";\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 SensorSpectralReferenceConditions,\n SensorSpectralResponseScientificStatus\n} from \"./spectral-response.js\";\nimport type {\n SensorSpatioSpectralIrradianceReduction\n} from \"./spatio-spectral-reduction.js\";\nimport { requireInputObject, requireInputKeys, rejectUnknownVariantFields, requireConfigRecord as requireRecord, requireConfigString as requireNonEmptyString, requireConfigPositiveFinite as requirePositiveFinite } from \"../core/record-validation.js\";\nimport { approximatelyEqual } from \"../core/shared-helpers.js\";\n\n\nexport type SensorResponseSourcePlane =\n | \"sensor-package-incident\"\n | \"site-incident\";\n\nexport type SensorResponseIncidentAreaBasis =\n | {\n kind: \"geometric-sensitive-aperture\";\n areaSquareMicrometers: number;\n }\n | {\n kind: \"full-site-cell\";\n areaSquareMicrometers: number;\n }\n | {\n kind: \"effective-collection-area\";\n areaSquareMicrometers: number;\n };\n\nexport type SensorResponseSpatialModel =\n | {\n kind:\n \"uniform-over-geometric-sensitive-aperture\";\n scientificStatus:\n SensorSpectralResponseScientificStatus;\n evidence: readonly EvidenceProvenance[];\n limitation?: string;\n }\n | {\n kind: \"not-established\";\n limitation: string;\n };\n\nexport type SensorResponseReferenceConditionPolicy =\n | {\n kind: \"exact-match-required\";\n }\n | {\n kind: \"assume-compatible\";\n limitation: string;\n evidence: readonly EvidenceProvenance[];\n };\n\nexport interface SensorResponseApplicationProfile {\n schemaVersion: \"0.1.0\";\n profileId: string;\n spectralResponseProfileId: string;\n colorSamplingProfileId: string;\n channelId: string;\n samplingApertureProfileId: string;\n opticalStackProfileId: string;\n evidence: readonly EvidenceProvenance[];\n incidentAreaBasis:\n SensorResponseIncidentAreaBasis;\n spatialResponseModel:\n SensorResponseSpatialModel;\n referenceConditionPolicy:\n SensorResponseReferenceConditionPolicy;\n}\n\nexport interface SourcedSensorResponseSourcePlane {\n value: SensorResponseSourcePlane;\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface AssessSensorResponseApplicationCompatibilityInput {\n reduction:\n SensorSpatioSpectralIrradianceReduction;\n applicationProfile:\n SensorResponseApplicationProfile;\n sourcePlane:\n SourcedSensorResponseSourcePlane;\n operatingConditions?:\n SensorSpectralReferenceConditions;\n}\n\nexport type SensorResponseApplicationCompatibilityBlocker =\n | \"spectral-response-profile-id-mismatch\"\n | \"color-sampling-profile-id-mismatch\"\n | \"channel-id-mismatch\"\n | \"sampling-aperture-profile-id-missing\"\n | \"sampling-aperture-profile-id-mismatch\"\n | \"optical-stack-profile-id-missing\"\n | \"optical-stack-profile-id-mismatch\"\n | \"source-plane-mismatch\"\n | \"wavelength-basis-unresolved\"\n | \"incident-area-basis-not-currently-integrated\"\n | \"incident-area-mismatch\"\n | \"spatial-response-uniformity-not-established\"\n | \"response-reference-conditions-not-declared\"\n | \"operating-conditions-not-declared\"\n | \"operating-conditions-mismatch\";\n\nexport type SensorResponseSignalPath =\n | \"photon-rate-to-electrons\"\n | \"radiant-power-to-current\";\n\nexport interface SensorResponseApplicationCompatibilityAssessment {\n applicationProfileId: string;\n spectralResponseProfileId: string;\n colorSamplingProfileId: string;\n channelId: string;\n responseScope:\n SensorSpatioSpectralIrradianceReduction[\"responseScope\"];\n requiredSourcePlane:\n SensorResponseSourcePlane;\n suppliedSourcePlane:\n SensorResponseSourcePlane;\n sourcePlaneMatched: boolean;\n responseIncidentAreaBasis:\n SensorResponseIncidentAreaBasis;\n currentlyIntegratedAreaBasis:\n \"geometric-sensitive-aperture\";\n geometricApertureAreaSquareMicrometers:\n number;\n nominalSiteCellAreaSquareMicrometers?:\n number;\n spatialResponseModel:\n SensorResponseSpatialModel;\n referenceConditionPolicy:\n SensorResponseReferenceConditionPolicy;\n responseReferenceConditions?:\n SensorSpectralReferenceConditions;\n operatingConditions?:\n SensorSpectralReferenceConditions;\n structuralCompatibilityEstablished:\n boolean;\n compatibilityStatus:\n | \"compatible\"\n | \"compatible-approximation\"\n | \"blocked\";\n blockers:\n readonly SensorResponseApplicationCompatibilityBlocker[];\n requiredSignalPath:\n SensorResponseSignalPath;\n quantifiedResponseUncertaintyAvailable:\n boolean;\n responseApplicationPerformed: false;\n signalConversionAuthorized: false;\n temporalIntegrationAuthorized: false;\n photonConversionPerformed: false;\n electronConversionPerformed: false;\n currentConversionPerformed: false;\n operatingRangeCompatibilityAssessed: false;\n spatiallyVaryingResponseSupported: false;\n componentEvidence: {\n applicationProfile:\n readonly EvidenceProvenance[];\n sourcePlane:\n readonly EvidenceProvenance[];\n spatialResponse:\n readonly EvidenceProvenance[];\n referenceConditionAssumption:\n readonly EvidenceProvenance[];\n response:\n SensorSpatioSpectralIrradianceReduction[\"componentEvidence\"][\"spectral\"];\n };\n}\n\nfunction parseIncidentAreaBasis(\n value: unknown,\n path: string\n): SensorResponseIncidentAreaBasis {\n const record =\n requireRecord(value, path, [\"areaSquareMicrometers\", \"kind\"]);\n const areaSquareMicrometers =\n requirePositiveFinite(\n record.areaSquareMicrometers,\n path + \".areaSquareMicrometers\"\n );\n\n if (\n record.kind !==\n \"geometric-sensitive-aperture\" &&\n record.kind !== \"full-site-cell\" &&\n record.kind !==\n \"effective-collection-area\"\n ) {\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n }\n\n return {\n kind: record.kind,\n areaSquareMicrometers\n };\n}\n\nfunction parseSpatialResponseModel(\n value: unknown,\n path: string\n): SensorResponseSpatialModel {\n const record =\n requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", { \"not-established\": [\"kind\", \"limitation\"], \"uniform-over-geometric-sensitive-aperture\": [\"kind\", \"scientificStatus\", \"evidence\", \"limitation\"] }, path);\n\n if (\n record.kind === \"not-established\"\n ) {\n return {\n kind: \"not-established\",\n limitation: requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n if (\n record.kind !==\n \"uniform-over-geometric-sensitive-aperture\"\n ) {\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n }\n\n if (\n record.scientificStatus !==\n \"calibrated\" &&\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \".scientificStatus is invalid.\"\n );\n }\n\n const limitation =\n record.limitation === undefined\n ? undefined\n : requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n );\n\n if (\n record.scientificStatus ===\n \"approximation\" &&\n limitation === undefined\n ) {\n throw new InvalidConfigurationError(\n path +\n \".limitation is required for an approximation.\"\n );\n }\n\n return {\n kind:\n \"uniform-over-geometric-sensitive-aperture\",\n scientificStatus:\n record.scientificStatus,\n evidence: parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n ),\n ...(limitation === undefined\n ? {}\n : { limitation })\n };\n}\n\nexport function parseReferenceConditionPolicy(\n value: unknown,\n path: string\n): SensorResponseReferenceConditionPolicy {\n const record =\n requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", { \"exact-match-required\": [\"kind\"], \"assume-compatible\": [\"kind\", \"limitation\", \"evidence\"] }, path);\n\n if (\n record.kind ===\n \"exact-match-required\"\n ) {\n return {\n kind: \"exact-match-required\"\n };\n }\n\n if (\n record.kind === \"assume-compatible\"\n ) {\n return {\n kind: \"assume-compatible\",\n limitation: requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n ),\n evidence: parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\n/**\n * Validates untrusted input and returns it as a normalized, typed value. Unknown enum values,\n * missing required fields and inconsistent scientific data are rejected.\n *\n * The profile states the source plane, incident-area basis, spatial uniformity and reference\n * conditions under which a response applies.\n * @param value - Untrusted data. TypeScript types alone are not validation.\n * @returns The result. Success does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the package export and its full type definitions.\n */\nexport function parseSensorResponseApplicationProfile(\n value: unknown\n): SensorResponseApplicationProfile {\n const record = requireRecord(\n value,\n \"sensorResponseApplication\", [\"schemaVersion\", \"profileId\", \"spectralResponseProfileId\", \"colorSamplingProfileId\", \"channelId\", \"samplingApertureProfileId\", \"opticalStackProfileId\", \"evidence\", \"incidentAreaBasis\", \"spatialResponseModel\", \"referenceConditionPolicy\"]\n );\n\n if (\n record.schemaVersion !== \"0.1.0\"\n ) {\n throw new InvalidConfigurationError(\n 'sensorResponseApplication.schemaVersion must be \"0.1.0\".'\n );\n }\n\n return {\n schemaVersion: \"0.1.0\",\n profileId: requireNonEmptyString(\n record.profileId,\n \"sensorResponseApplication.profileId\"\n ),\n spectralResponseProfileId:\n requireNonEmptyString(\n record.spectralResponseProfileId,\n \"sensorResponseApplication.spectralResponseProfileId\"\n ),\n colorSamplingProfileId:\n requireNonEmptyString(\n record.colorSamplingProfileId,\n \"sensorResponseApplication.colorSamplingProfileId\"\n ),\n channelId: requireNonEmptyString(\n record.channelId,\n \"sensorResponseApplication.channelId\"\n ),\n samplingApertureProfileId:\n requireNonEmptyString(\n record.samplingApertureProfileId,\n \"sensorResponseApplication.samplingApertureProfileId\"\n ),\n opticalStackProfileId:\n requireNonEmptyString(\n record.opticalStackProfileId,\n \"sensorResponseApplication.opticalStackProfileId\"\n ),\n evidence: parseEvidenceList(\n record.evidence,\n \"sensorResponseApplication.evidence\"\n ),\n incidentAreaBasis:\n parseIncidentAreaBasis(\n record.incidentAreaBasis,\n \"sensorResponseApplication.incidentAreaBasis\"\n ),\n spatialResponseModel:\n parseSpatialResponseModel(\n record.spatialResponseModel,\n \"sensorResponseApplication.spatialResponseModel\"\n ),\n referenceConditionPolicy:\n parseReferenceConditionPolicy(\n record.referenceConditionPolicy,\n \"sensorResponseApplication.referenceConditionPolicy\"\n )\n };\n}\n\nfunction parseSourcePlane(\n value:\n SourcedSensorResponseSourcePlane\n): SourcedSensorResponseSourcePlane {\n const record = requireRecord(\n value,\n \"sourcePlane\", [\"value\", \"evidence\"]\n );\n if (\n record.value !==\n \"sensor-package-incident\" &&\n record.value !== \"site-incident\"\n ) {\n throw new InvalidConfigurationError(\n \"sourcePlane.value is invalid.\"\n );\n }\n return {\n value: record.value,\n evidence: parseEvidenceList(\n record.evidence,\n \"sourcePlane.evidence\"\n )\n };\n}\n\nfunction requiredSourcePlane(\n scope:\n SensorSpatioSpectralIrradianceReduction[\"responseScope\"]\n): SensorResponseSourcePlane {\n return scope ===\n \"sensor-package-incident-effective-channel-response\"\n ? \"sensor-package-incident\"\n : \"site-incident\";\n}\n\n\nexport function conditionsMatch(\n reference:\n SensorSpectralReferenceConditions,\n operating:\n SensorSpectralReferenceConditions\n): boolean {\n if (\n reference.temperatureC !==\n undefined &&\n operating.temperatureC !==\n reference.temperatureC\n ) {\n return false;\n }\n if (\n reference\n .incidenceAngleDegreesFromNormal !==\n undefined &&\n operating\n .incidenceAngleDegreesFromNormal !==\n reference\n .incidenceAngleDegreesFromNormal\n ) {\n return false;\n }\n if (\n reference.polarization !==\n undefined &&\n operating.polarization !==\n reference.polarization\n ) {\n return false;\n }\n return true;\n}\n\nfunction validateReductionBoundary(\n reduction:\n SensorSpatioSpectralIrradianceReduction\n): number {\n requireInputObject(reduction, \"reduction input\");\n if (\n reduction.outputMeaning !==\n \"pre-response-spatio-spectral-radiometric-reduction\" ||\n reduction\n .spectralResponseApplicationPerformed !==\n false ||\n reduction.quantumEfficiencyApplied !==\n false ||\n reduction.spectralResponsivityApplied !==\n false ||\n reduction.temporalIntegrationApplied !==\n false\n ) {\n throw new InvalidScientificInputError(\n \"reduction must remain a pre-response, pre-temporal spatio-spectral result.\"\n );\n }\n\n if (\n typeof reduction\n .geometricApertureAreaSquareMicrometers !==\n \"number\" ||\n !Number.isFinite(\n reduction\n .geometricApertureAreaSquareMicrometers\n ) ||\n reduction\n .geometricApertureAreaSquareMicrometers <=\n 0\n ) {\n throw new InvalidScientificInputError(\n \"reduction.geometricApertureAreaSquareMicrometers is required and must be positive.\"\n );\n }\n\n return reduction\n .geometricApertureAreaSquareMicrometers;\n}\n\n/**\n * Checks whether the source plane, area, profile, channel and reference conditions allow the\n * selected way of applying the response.\n *\n * Passing this alone does not allow converting light to signal. The per-bin operating-range check\n * and the EQE or A/W conversion are separate steps.\n * @param input - The input; see `AssessSensorResponseApplicationCompatibilityInput` for its fields, units and coordinates.\n * @returns The assessment. Read its structured blockers before acting on an authorization.\n *\n * @see docs/API_REFERENCE.md for the package export and its full type definitions.\n */\nexport function assessSensorResponseApplicationCompatibility(\n input:\n AssessSensorResponseApplicationCompatibilityInput\n): CalculationResult<SensorResponseApplicationCompatibilityAssessment> {\n requireInputKeys(input, \"assessSensorResponseApplicationCompatibility\", [\"reduction\", \"applicationProfile\", \"sourcePlane\", \"operatingConditions\"]);\n const geometricArea =\n validateReductionBoundary(\n input.reduction\n );\n const profile =\n parseSensorResponseApplicationProfile(\n input.applicationProfile\n );\n const sourcePlane =\n parseSourcePlane(input.sourcePlane);\n const blockers:\n SensorResponseApplicationCompatibilityBlocker[] =\n [];\n\n if (\n profile.spectralResponseProfileId !==\n input.reduction.responseProfileId\n ) {\n blockers.push(\n \"spectral-response-profile-id-mismatch\"\n );\n }\n if (\n profile.colorSamplingProfileId !==\n input.reduction\n .colorSamplingProfileId\n ) {\n blockers.push(\n \"color-sampling-profile-id-mismatch\"\n );\n }\n if (\n profile.channelId !==\n input.reduction.channelId\n ) {\n blockers.push(\n \"channel-id-mismatch\"\n );\n }\n\n const samplingApertureProfileId =\n input.reduction\n .samplingApertureProfileId;\n if (\n samplingApertureProfileId ===\n undefined\n ) {\n blockers.push(\n \"sampling-aperture-profile-id-missing\"\n );\n } else if (\n samplingApertureProfileId !==\n profile.samplingApertureProfileId\n ) {\n blockers.push(\n \"sampling-aperture-profile-id-mismatch\"\n );\n }\n\n const opticalStackProfileId =\n input.reduction\n .opticalStackProfileId;\n if (\n opticalStackProfileId === undefined\n ) {\n blockers.push(\n \"optical-stack-profile-id-missing\"\n );\n } else if (\n opticalStackProfileId !==\n profile.opticalStackProfileId\n ) {\n blockers.push(\n \"optical-stack-profile-id-mismatch\"\n );\n }\n\n const requiredPlane =\n requiredSourcePlane(\n input.reduction.responseScope\n );\n const sourcePlaneMatched =\n sourcePlane.value === requiredPlane;\n if (!sourcePlaneMatched) {\n blockers.push(\n \"source-plane-mismatch\"\n );\n }\n\n if (\n !input.reduction\n .wavelengthBasisResolved\n ) {\n blockers.push(\n \"wavelength-basis-unresolved\"\n );\n }\n\n if (\n profile.incidentAreaBasis.kind !==\n \"geometric-sensitive-aperture\"\n ) {\n blockers.push(\n \"incident-area-basis-not-currently-integrated\"\n );\n } else if (\n !approximatelyEqual(\n profile.incidentAreaBasis\n .areaSquareMicrometers,\n geometricArea\n )\n ) {\n blockers.push(\n \"incident-area-mismatch\"\n );\n }\n\n if (\n profile.spatialResponseModel.kind ===\n \"not-established\"\n ) {\n blockers.push(\n \"spatial-response-uniformity-not-established\"\n );\n }\n\n if (\n profile.referenceConditionPolicy.kind ===\n \"exact-match-required\"\n ) {\n const referenceConditions =\n input.reduction\n .responseReferenceConditions;\n if (\n referenceConditions === undefined\n ) {\n blockers.push(\n \"response-reference-conditions-not-declared\"\n );\n } else if (\n input.operatingConditions ===\n undefined\n ) {\n blockers.push(\n \"operating-conditions-not-declared\"\n );\n } else if (\n !conditionsMatch(\n referenceConditions,\n input.operatingConditions\n )\n ) {\n blockers.push(\n \"operating-conditions-mismatch\"\n );\n }\n }\n\n const structurallyCompatible =\n blockers.length === 0;\n\n const approximation =\n input.reduction\n .responseScientificStatus ===\n \"approximation\" ||\n (\n profile.spatialResponseModel.kind ===\n \"uniform-over-geometric-sensitive-aperture\" &&\n profile.spatialResponseModel\n .scientificStatus ===\n \"approximation\"\n ) ||\n profile.referenceConditionPolicy.kind ===\n \"assume-compatible\";\n\n const compatibilityStatus =\n structurallyCompatible\n ? approximation\n ? \"compatible-approximation\"\n : \"compatible\"\n : \"blocked\";\n\n const spatialEvidence =\n profile.spatialResponseModel.kind ===\n \"uniform-over-geometric-sensitive-aperture\"\n ? profile.spatialResponseModel.evidence\n : [];\n const referenceConditionEvidence =\n profile.referenceConditionPolicy.kind ===\n \"assume-compatible\"\n ? profile.referenceConditionPolicy\n .evidence\n : [];\n\n return calculatedResult(\n {\n applicationProfileId:\n profile.profileId,\n spectralResponseProfileId:\n input.reduction\n .responseProfileId,\n colorSamplingProfileId:\n input.reduction\n .colorSamplingProfileId,\n channelId:\n input.reduction.channelId,\n responseScope:\n input.reduction.responseScope,\n requiredSourcePlane:\n requiredPlane,\n suppliedSourcePlane:\n sourcePlane.value,\n sourcePlaneMatched,\n responseIncidentAreaBasis:\n profile.incidentAreaBasis,\n currentlyIntegratedAreaBasis:\n \"geometric-sensitive-aperture\",\n geometricApertureAreaSquareMicrometers:\n geometricArea,\n ...(input.reduction\n .nominalSiteCellAreaSquareMicrometers ===\n undefined\n ? {}\n : {\n nominalSiteCellAreaSquareMicrometers:\n input.reduction\n .nominalSiteCellAreaSquareMicrometers\n }),\n spatialResponseModel:\n profile.spatialResponseModel,\n referenceConditionPolicy:\n profile.referenceConditionPolicy,\n ...(input.reduction\n .responseReferenceConditions ===\n undefined\n ? {}\n : {\n responseReferenceConditions:\n input.reduction\n .responseReferenceConditions\n }),\n ...(input.operatingConditions ===\n undefined\n ? {}\n : {\n operatingConditions:\n input.operatingConditions\n }),\n structuralCompatibilityEstablished:\n structurallyCompatible,\n compatibilityStatus,\n blockers,\n requiredSignalPath:\n input.reduction\n .sourceResponseKind ===\n \"effective-spectral-responsivity\"\n ? \"radiant-power-to-current\"\n : \"photon-rate-to-electrons\",\n quantifiedResponseUncertaintyAvailable:\n input.reduction\n .responseUncertainty.kind ===\n \"relative\",\n responseApplicationPerformed:\n false,\n signalConversionAuthorized:\n false,\n temporalIntegrationAuthorized:\n false,\n photonConversionPerformed:\n false,\n electronConversionPerformed:\n false,\n currentConversionPerformed:\n false,\n operatingRangeCompatibilityAssessed:\n false,\n spatiallyVaryingResponseSupported:\n false,\n componentEvidence: {\n applicationProfile:\n profile.evidence,\n sourcePlane:\n sourcePlane.evidence,\n spatialResponse:\n spatialEvidence,\n referenceConditionAssumption:\n referenceConditionEvidence,\n response:\n input.reduction\n .componentEvidence.spectral\n }\n },\n \"sensor-response-application-compatibility\",\n \"1.0.0\",\n [\n \"This result is a structural compatibility gate only; it never authorizes or performs sensor-response signal conversion.\",\n \"Response reference plane is derived from responseScope. Package-incident and site-incident inputs are not interchangeable.\",\n \"The current spatio-spectral reducer integrates the geometric sensitive aperture only. Full-site-cell and effective-collection-area response normalizations remain blocked until matching radiometric integrations exist.\",\n \"A scalar wavelength-only response may be applied after spatial reduction only when uniform/separable response over the integrated geometric aperture is explicitly established or declared as an approximation.\",\n \"Exact reference-condition matching is required when that policy is selected because temperature, incidence-angle and polarization dependence are not modeled.\",\n \"An unresolved wavelength basis is incompatible with physical response application.\",\n \"Typical total-pixel QE definitions can include fill factor and microlens effects; they must not be applied to geometric-sensitive-aperture flux unless the response normalization explicitly matches that area basis.\",\n \"Response linearity/dynamic-range validity is not assessed by this gate and remains required before a future conversion can claim calibrated applicability.\",\n \"EQE/filter×EQE responses require a future photon-rate→electron path; A/W responsivity requires a separate radiant-power→current path.\",\n \"Temporal integration, photons/electrons/current, noise, saturation, ADC/RAW conversion and reconstruction remain downstream.\"\n ]\n );\n}\n"]}
|
|
@@ -18,10 +18,9 @@ import { InvalidScientificInputError } from "../core/validation.js";
|
|
|
18
18
|
import { parseSensorColorSamplingProfile } from "./color-sampling.js";
|
|
19
19
|
import { createSensorSpectralResponseChannelBinding, requireCurrentSensorSpectralResponseChannelBinding, parseSensorSpectralResponseProfile, resolveParsedSensorSpectralResponseAtWavelength } from "./spectral-response.js";
|
|
20
20
|
import { requireInputObject, requireInputKeys, rejectUnknownVariantFields, requireConfigRecord as requireRecord, requireConfigString as requireNonEmptyString, requireConfigPositiveFinite as requirePositiveFiniteConfiguration, requireInputNonNegativeFinite as requireNonNegativeFiniteInput, requireInputPositiveFinite as requirePositiveFiniteInput, requireInputNonNegativeSafeInteger as requireSafeNonNegativeInteger } from "../core/record-validation.js";
|
|
21
|
-
import { addCompensated } from "../core/shared-helpers.js";
|
|
21
|
+
import { addCompensated, approximatelyEqual } from "../core/shared-helpers.js";
|
|
22
22
|
import { parseReferenceConditionPolicy as parseConditionPolicy } from "./response-application-compatibility.js";
|
|
23
23
|
import { parseUncertainty } from "./response-operating-range.js";
|
|
24
|
-
const REDUCTION_TOLERANCE = 1e-10;
|
|
25
24
|
function parseElectricalConditions(value, path) {
|
|
26
25
|
const record = requireRecord(value, path, ["bias", "readoutLoad"]);
|
|
27
26
|
const bias = requireRecord(record.bias, path + ".bias", null);
|
|
@@ -128,11 +127,6 @@ function canonicalJson(value) {
|
|
|
128
127
|
unsupportedValueMessage: "A/W photocurrent identity data must be plain JSON data."
|
|
129
128
|
});
|
|
130
129
|
}
|
|
131
|
-
function approximatelyEqual(actual, expected) {
|
|
132
|
-
const scale = Math.max(1, Math.abs(actual), Math.abs(expected));
|
|
133
|
-
return (Math.abs(actual - expected) <=
|
|
134
|
-
REDUCTION_TOLERANCE * scale);
|
|
135
|
-
}
|
|
136
130
|
function electricalConditionsMatch(reference, operating) {
|
|
137
131
|
return (canonicalJson(reference) ===
|
|
138
132
|
canonicalJson(operating));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"responsivity-photocurrent.js","sourceRoot":"","sources":["../../src/sensor/responsivity-photocurrent.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Responsivity photocurrent: converts light power to detector current using responsivity in amperes\n * per watt (A/W).\n *\n * For each wavelength bin, current = responsivity × radiant power; the bins are summed. The result is\n * the steady (quasi-static) current magnitude at the detector terminals. The electrical bias and load\n * conditions under which the responsivity applies are explicit. This is not EQE, an electron rate, a\n * transimpedance voltage or RAW. Fast-changing current needs a separate time-dependent detector model.\n * @see docs/MOTION_AND_SIGNAL.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport {\n approximationResult,\n type CalculationResult\n} from \"../core/calculation-result.js\";\nimport { stringifyCanonicalJson } from \"../core/canonical-json.js\";\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 parseSensorColorSamplingProfile,\n type SensorColorSamplingProfile\n} from \"./color-sampling.js\";\nimport type {\n SensorResponseApplicationCompatibilityAssessment\n} from \"./response-application-compatibility.js\";\nimport type {\n SensorResponseOperatingRangeAssessment\n} from \"./response-operating-range.js\";\nimport {\n createSensorSpectralResponseChannelBinding,\n requireCurrentSensorSpectralResponseChannelBinding,\n parseSensorSpectralResponseProfile,\n resolveParsedSensorSpectralResponseAtWavelength,\n type ResolvedSensorSpectralResponse,\n type SensorSpectralResponseProfile,\n type SensorSpectralResponseScientificStatus,\n type SensorSpectralResponseUncertainty\n} from \"./spectral-response.js\";\nimport type {\n SensorSpatioSpectralIrradianceReduction,\n SensorSpatioSpectralWavelengthReduction\n} from \"./spatio-spectral-reduction.js\";\nimport { requireInputObject, requireInputKeys, rejectUnknownVariantFields, requireConfigRecord as requireRecord, requireConfigString as requireNonEmptyString, requireConfigPositiveFinite as requirePositiveFiniteConfiguration, requireInputNonNegativeFinite as requireNonNegativeFiniteInput, requireInputPositiveFinite as requirePositiveFiniteInput, requireInputNonNegativeSafeInteger as requireSafeNonNegativeInteger } from \"../core/record-validation.js\";\nimport { addCompensated } from \"../core/shared-helpers.js\";\nimport { parseReferenceConditionPolicy as parseConditionPolicy } from \"./response-application-compatibility.js\";\nimport { parseUncertainty } from \"./response-operating-range.js\";\n\nconst REDUCTION_TOLERANCE = 1e-10;\n\nexport type SensorResponsivityBiasCondition =\n | {\n kind: \"zero-bias-photovoltaic\";\n }\n | {\n kind: \"reverse-biased\";\n magnitudeVolts: number;\n };\n\nexport type SensorResponsivityReadoutLoadCondition =\n | {\n kind: \"virtual-ground-current-readout\";\n }\n | {\n kind: \"finite-input-impedance\";\n inputImpedanceOhms: number;\n };\n\nexport interface SensorResponsivityElectricalConditions {\n bias: SensorResponsivityBiasCondition;\n readoutLoad:\n SensorResponsivityReadoutLoadCondition;\n}\n\nexport type SensorResponsivityElectricalConditionPolicy =\n | {\n kind: \"exact-match-required\";\n }\n | {\n kind: \"assume-compatible\";\n limitation: string;\n evidence: readonly EvidenceProvenance[];\n };\n\nexport interface SensorResponsivityElectricalApplicabilityProfile {\n schemaVersion: \"0.1.0\";\n profileId: string;\n responseApplicationProfileId: string;\n spectralResponseProfileId: string;\n colorSamplingProfileId: string;\n channelId: string;\n outputMeaning:\n \"detector-terminal-photocurrent-magnitude\";\n referenceConditions:\n SensorResponsivityElectricalConditions;\n conditionPolicy:\n SensorResponsivityElectricalConditionPolicy;\n scientificStatus:\n SensorSpectralResponseScientificStatus;\n uncertainty:\n SensorSpectralResponseUncertainty;\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface CalculateSensorResponsivityPhotocurrentInput {\n reduction:\n SensorSpatioSpectralIrradianceReduction;\n compatibility:\n SensorResponseApplicationCompatibilityAssessment;\n operatingRange:\n SensorResponseOperatingRangeAssessment;\n colorSamplingProfile:\n SensorColorSamplingProfile;\n spectralResponseProfile:\n SensorSpectralResponseProfile;\n electricalApplicabilityProfile:\n SensorResponsivityElectricalApplicabilityProfile;\n operatingElectricalConditions:\n SensorResponsivityElectricalConditions;\n}\n\nexport interface SensorResponsivityWavelengthCurrentContribution {\n spectralSampleIndex: number;\n wavelengthNanometers: number;\n wavelengthMeasureNanometers: number;\n geometricApertureIncidentSpectralFluxWattsPerNanometer:\n number;\n radiantPowerContributionWatts: number;\n spectralResponsivityAmperesPerWatt:\n number;\n responseInterpolationUsed: boolean;\n photocurrentMagnitudeContributionAmperes:\n number;\n}\n\nexport interface SensorResponsivityPhotocurrent {\n colorSamplingProfileId: string;\n responseProfileId: string;\n responseApplicationProfileId: string;\n operatingRangeProfileId: string;\n electricalApplicabilityProfileId:\n string;\n /** The exact source colour site. Results produced by the engine fill this in. */\n site?: {\n x: number;\n y: number;\n };\n channelId: string;\n sourceResponseKind:\n \"effective-spectral-responsivity\";\n responseScope:\n SensorSpatioSpectralIrradianceReduction[\"responseScope\"];\n responseReferencePlane:\n SensorResponseApplicationCompatibilityAssessment[\"requiredSourcePlane\"];\n wavelengthBasis:\n SensorSpatioSpectralIrradianceReduction[\"wavelengthBasis\"];\n wavelengthRangeNanometers:\n SensorSpatioSpectralIrradianceReduction[\"wavelengthRangeNanometers\"];\n electricalReferenceConditions:\n SensorResponsivityElectricalConditions;\n operatingElectricalConditions:\n SensorResponsivityElectricalConditions;\n electricalConditionPolicy:\n SensorResponsivityElectricalConditionPolicy;\n electricalCompatibility:\n | \"exact-match\"\n | \"assumed-compatible\";\n spectralNodeCount: number;\n perWavelength:\n readonly SensorResponsivityWavelengthCurrentContribution[];\n photocurrentMagnitudeAmperes: number;\n currentSignConvention:\n \"magnitude-only-no-circuit-polarity\";\n summationMethod:\n \"kahan-compensated\";\n responseApplicationPerformed: true;\n spectralResponsivityApplied: true;\n quantumEfficiencyApplied: false;\n photonRateCalculated: false;\n electronRateCalculated: false;\n currentCalculated: true;\n chargeCalculated: false;\n temporalResponseModel:\n \"quasi-static-steady-state-only\";\n detectorBandwidthModeled: false;\n transimpedanceGainApplied: false;\n voltageCalculated: false;\n temporalIntegrationApplied: false;\n exposureDurationApplied: false;\n saturationAssessed: false;\n readoutElectronicsLinearityAssessed:\n false;\n shotNoiseApplied: false;\n readNoiseApplied: false;\n adcQuantizationApplied: false;\n rawCodeValueProduced: false;\n responseUncertaintyPropagated: false;\n electricalApplicabilityUncertaintyPropagated:\n false;\n quadratureConvergenceErrorEstimated:\n false;\n componentEvidence: {\n electricalApplicability:\n readonly EvidenceProvenance[];\n electricalConditionAssumption:\n readonly EvidenceProvenance[];\n };\n}\n\ninterface CompensatedSum {\n sum: number;\n correction: number;\n}\n\nfunction parseElectricalConditions(\n value: unknown,\n path: string\n): SensorResponsivityElectricalConditions {\n const record = requireRecord(\n value,\n path, [\"bias\", \"readoutLoad\"]\n );\n const bias = requireRecord(\n record.bias,\n path + \".bias\", null\n );\n rejectUnknownVariantFields(bias, \"kind\", { \"zero-bias-photovoltaic\": [\"kind\"], \"reverse-biased\": [\"kind\", \"magnitudeVolts\"] }, path + \".bias\");\n const readoutLoad = requireRecord(\n record.readoutLoad,\n path + \".readoutLoad\", null\n );\n rejectUnknownVariantFields(readoutLoad, \"kind\", { \"virtual-ground-current-readout\": [\"kind\"], \"finite-input-impedance\": [\"kind\", \"inputImpedanceOhms\"] }, path + \".readoutLoad\");\n\n const parsedBias:\n SensorResponsivityBiasCondition =\n bias.kind ===\n \"zero-bias-photovoltaic\"\n ? {\n kind:\n \"zero-bias-photovoltaic\"\n }\n : bias.kind ===\n \"reverse-biased\"\n ? {\n kind:\n \"reverse-biased\",\n magnitudeVolts:\n requirePositiveFiniteConfiguration(\n bias.magnitudeVolts,\n path +\n \".bias.magnitudeVolts\"\n )\n }\n : ((): never => {\n throw new InvalidConfigurationError(\n path +\n \".bias.kind is invalid.\"\n );\n })();\n\n const parsedReadout:\n SensorResponsivityReadoutLoadCondition =\n readoutLoad.kind ===\n \"virtual-ground-current-readout\"\n ? {\n kind:\n \"virtual-ground-current-readout\"\n }\n : readoutLoad.kind ===\n \"finite-input-impedance\"\n ? {\n kind:\n \"finite-input-impedance\",\n inputImpedanceOhms:\n requirePositiveFiniteConfiguration(\n readoutLoad\n .inputImpedanceOhms,\n path +\n \".readoutLoad.inputImpedanceOhms\"\n )\n }\n : ((): never => {\n throw new InvalidConfigurationError(\n path +\n \".readoutLoad.kind is invalid.\"\n );\n })();\n\n return {\n bias: parsedBias,\n readoutLoad: parsedReadout\n };\n}\n\n/**\n * Validates untrusted input and returns it as a normalized, typed value. Unknown enum values,\n * missing required fields and inconsistent scientific data are rejected.\n *\n * The profile states the electrical bias and load conditions under which an A/W responsivity applies.\n * @param value - Untrusted data. TypeScript types alone are not validation.\n * @returns The result. Success does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the package export and its full type definitions.\n */\nexport function parseSensorResponsivityElectricalApplicabilityProfile(\n value: unknown\n): SensorResponsivityElectricalApplicabilityProfile {\n const record = requireRecord(\n value,\n \"sensorResponsivityElectricalApplicability\", [\"schemaVersion\", \"outputMeaning\", \"scientificStatus\", \"uncertainty\", \"profileId\", \"responseApplicationProfileId\", \"spectralResponseProfileId\", \"colorSamplingProfileId\", \"channelId\", \"referenceConditions\", \"conditionPolicy\", \"evidence\"]\n );\n\n if (\n record.schemaVersion !== \"0.1.0\"\n ) {\n throw new InvalidConfigurationError(\n 'sensorResponsivityElectricalApplicability.schemaVersion must be \"0.1.0\".'\n );\n }\n if (\n record.outputMeaning !==\n \"detector-terminal-photocurrent-magnitude\"\n ) {\n throw new InvalidConfigurationError(\n \"sensorResponsivityElectricalApplicability.outputMeaning is invalid.\"\n );\n }\n if (\n record.scientificStatus !==\n \"calibrated\" &&\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n \"sensorResponsivityElectricalApplicability.scientificStatus is invalid.\"\n );\n }\n\n const uncertainty =\n parseUncertainty(\n record.uncertainty,\n \"sensorResponsivityElectricalApplicability.uncertainty\"\n );\n\n if (\n record.scientificStatus ===\n \"calibrated\" &&\n uncertainty.kind ===\n \"not-quantified\"\n ) {\n throw new InvalidConfigurationError(\n \"A calibrated electrical applicability profile must declare quantified relative uncertainty.\"\n );\n }\n\n return {\n schemaVersion: \"0.1.0\",\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"sensorResponsivityElectricalApplicability.profileId\"\n ),\n responseApplicationProfileId:\n requireNonEmptyString(\n record\n .responseApplicationProfileId,\n \"sensorResponsivityElectricalApplicability.responseApplicationProfileId\"\n ),\n spectralResponseProfileId:\n requireNonEmptyString(\n record\n .spectralResponseProfileId,\n \"sensorResponsivityElectricalApplicability.spectralResponseProfileId\"\n ),\n colorSamplingProfileId:\n requireNonEmptyString(\n record.colorSamplingProfileId,\n \"sensorResponsivityElectricalApplicability.colorSamplingProfileId\"\n ),\n channelId:\n requireNonEmptyString(\n record.channelId,\n \"sensorResponsivityElectricalApplicability.channelId\"\n ),\n outputMeaning:\n \"detector-terminal-photocurrent-magnitude\",\n referenceConditions:\n parseElectricalConditions(\n record.referenceConditions,\n \"sensorResponsivityElectricalApplicability.referenceConditions\"\n ),\n conditionPolicy:\n parseConditionPolicy(\n record.conditionPolicy,\n \"sensorResponsivityElectricalApplicability.conditionPolicy\"\n ),\n scientificStatus:\n record.scientificStatus,\n uncertainty,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"sensorResponsivityElectricalApplicability.evidence\"\n )\n };\n}\n\n/**\n * Identity string for parsed plain data that ignores key order, so records with\n * the same content compare equal whatever order their properties were added in.\n */\nfunction canonicalJson(\n value: unknown\n): string {\n if (value === undefined) return \"undefined\";\n return stringifyCanonicalJson(value, {\n undefinedObjectProperties: \"omit\",\n nonFiniteNumberMessage:\n \"A/W photocurrent identity data must contain finite numbers.\",\n unsupportedValueMessage:\n \"A/W photocurrent identity data must be plain JSON data.\"\n });\n}\n\nfunction approximatelyEqual(\n actual: number,\n expected: number\n): boolean {\n const scale = Math.max(\n 1,\n Math.abs(actual),\n Math.abs(expected)\n );\n return (\n Math.abs(actual - expected) <=\n REDUCTION_TOLERANCE * scale\n );\n}\n\nfunction electricalConditionsMatch(\n reference:\n SensorResponsivityElectricalConditions,\n operating:\n SensorResponsivityElectricalConditions\n): boolean {\n return (\n canonicalJson(reference) ===\n canonicalJson(operating)\n );\n}\n\nfunction validateAuthorizationChain(\n reduction:\n SensorSpatioSpectralIrradianceReduction,\n compatibility:\n SensorResponseApplicationCompatibilityAssessment,\n operatingRange:\n SensorResponseOperatingRangeAssessment\n): void {\n requireInputObject(reduction, \"reduction input\");\n if (\n reduction.outputMeaning !==\n \"pre-response-spatio-spectral-radiometric-reduction\" ||\n reduction\n .spectralResponseApplicationPerformed !==\n false ||\n reduction\n .spectralResponsivityApplied !==\n false ||\n reduction.temporalIntegrationApplied !==\n false\n ) {\n throw new InvalidScientificInputError(\n \"reduction must remain pre-response and pre-temporal before A/W photocurrent conversion.\"\n );\n }\n\n if (\n !compatibility\n .structuralCompatibilityEstablished ||\n compatibility.compatibilityStatus ===\n \"blocked\" ||\n compatibility.blockers.length !== 0 ||\n !compatibility.sourcePlaneMatched ||\n compatibility.requiredSignalPath !==\n \"radiant-power-to-current\"\n ) {\n throw new InvalidScientificInputError(\n \"compatibility must establish a non-blocked radiant-power-to-current response path.\"\n );\n }\n\n if (\n compatibility\n .spectralResponseProfileId !==\n reduction.responseProfileId ||\n compatibility.colorSamplingProfileId !==\n reduction.colorSamplingProfileId ||\n compatibility.channelId !==\n reduction.channelId ||\n compatibility.responseScope !==\n reduction.responseScope\n ) {\n throw new InvalidScientificInputError(\n \"compatibility identities must exactly match the reduction.\"\n );\n }\n\n if (\n !operatingRange\n .operatingRangeCompatibilityAssessed ||\n !operatingRange\n .instantaneousResponseRangeCompatible ||\n !operatingRange\n .responseRateConversionAuthorized ||\n operatingRange.status === \"blocked\" ||\n operatingRange.blockers.length !== 0 ||\n operatingRange.requiredSignalPath !==\n \"radiant-power-to-current\" ||\n operatingRange\n .responseApplicationPerformed !==\n false ||\n operatingRange\n .currentConversionPerformed !== false ||\n operatingRange\n .temporalIntegrationAuthorized !== false ||\n !operatingRange\n .spectralNodeRangeCompatibilityAssessed ||\n operatingRange\n .spectralInputModel.kind !==\n \"per-spectral-bin\" ||\n operatingRange\n .spatialLinearityModel.kind !==\n \"linear-superposition-over-geometric-aperture\"\n ) {\n throw new InvalidScientificInputError(\n \"operatingRange must authorize a clean per-bin radiant-power-to-current path.\"\n );\n }\n\n if (\n operatingRange\n .spectralResponseProfileId !==\n reduction.responseProfileId ||\n operatingRange\n .colorSamplingProfileId !==\n reduction.colorSamplingProfileId ||\n operatingRange.channelId !==\n reduction.channelId ||\n operatingRange\n .responseApplicationProfileId !==\n compatibility.applicationProfileId\n ) {\n throw new InvalidScientificInputError(\n \"operatingRange identities must exactly match the reduction and compatibility assessment.\"\n );\n }\n}\n\nfunction validateReductionNodes(\n reduction:\n SensorSpatioSpectralIrradianceReduction\n): readonly SensorSpatioSpectralWavelengthReduction[] {\n if (\n !Array.isArray(\n reduction.perWavelength\n ) ||\n !Number.isSafeInteger(\n reduction.spectralNodeCount\n ) ||\n reduction.spectralNodeCount <= 0 ||\n reduction.perWavelength.length !==\n reduction.spectralNodeCount\n ) {\n throw new InvalidScientificInputError(\n \"reduction.perWavelength must contain exactly spectralNodeCount entries.\"\n );\n }\n\n let priorWavelength =\n Number.NEGATIVE_INFINITY;\n let normalizedWeightSum = 0;\n const totalPower:\n CompensatedSum = {\n sum: 0,\n correction: 0\n };\n\n reduction.perWavelength.forEach(\n (node, arrayIndex) => {\n const sampleIndex =\n requireSafeNonNegativeInteger(\n node.spectralSampleIndex,\n \"reduction.perWavelength[\" +\n arrayIndex +\n \"].spectralSampleIndex\"\n );\n if (sampleIndex !== arrayIndex) {\n throw new InvalidScientificInputError(\n \"reduction spectralSampleIndex values must form the exact contiguous range 0..spectralNodeCount-1.\"\n );\n }\n\n const wavelength =\n requirePositiveFiniteInput(\n node.wavelengthNanometers,\n \"reduction.perWavelength[\" +\n arrayIndex +\n \"].wavelengthNanometers\"\n );\n if (\n wavelength <= priorWavelength\n ) {\n throw new InvalidScientificInputError(\n \"reduction wavelength nodes must be strictly increasing.\"\n );\n }\n priorWavelength = wavelength;\n\n const measure =\n requirePositiveFiniteInput(\n node.wavelengthMeasureNanometers,\n \"reduction.perWavelength[\" +\n arrayIndex +\n \"].wavelengthMeasureNanometers\"\n );\n const normalizedWeight =\n requirePositiveFiniteInput(\n node.normalizedWavelengthWeight,\n \"reduction.perWavelength[\" +\n arrayIndex +\n \"].normalizedWavelengthWeight\"\n );\n const fluxDensity =\n requireNonNegativeFiniteInput(\n node\n .geometricApertureIncidentSpectralFluxWattsPerNanometer,\n \"reduction.perWavelength[\" +\n arrayIndex +\n \"].geometricApertureIncidentSpectralFluxWattsPerNanometer\"\n );\n const power =\n requireNonNegativeFiniteInput(\n node\n .wavelengthIntegratedGeometricApertureIncidentFluxContributionWatts,\n \"reduction.perWavelength[\" +\n arrayIndex +\n \"].wavelengthIntegratedGeometricApertureIncidentFluxContributionWatts\"\n );\n const expected =\n fluxDensity * measure;\n if (\n !Number.isFinite(expected) ||\n !approximatelyEqual(\n power,\n expected\n )\n ) {\n throw new InvalidScientificInputError(\n \"reduction per-wavelength radiant-power contribution must equal spectral flux density × d-lambda.\"\n );\n }\n\n normalizedWeightSum +=\n normalizedWeight;\n addCompensated(\n totalPower,\n power\n );\n }\n );\n\n if (\n !Number.isFinite(\n normalizedWeightSum\n ) ||\n !approximatelyEqual(\n normalizedWeightSum,\n 1\n )\n ) {\n throw new InvalidScientificInputError(\n \"reduction normalized wavelength weights must sum to 1.\"\n );\n }\n\n const reductionPower =\n requireNonNegativeFiniteInput(\n reduction\n .wavelengthIntegratedGeometricApertureIncidentFluxWatts,\n \"reduction.wavelengthIntegratedGeometricApertureIncidentFluxWatts\"\n );\n if (\n !approximatelyEqual(\n totalPower.sum,\n reductionPower\n )\n ) {\n throw new InvalidScientificInputError(\n \"reduction total geometric-aperture radiant power must match the per-wavelength sum.\"\n );\n }\n\n return reduction.perWavelength;\n}\n\nfunction validateOperatingRangeNodeBinding(\n reduction:\n SensorSpatioSpectralIrradianceReduction,\n nodes:\n readonly SensorSpatioSpectralWavelengthReduction[],\n operatingRange:\n SensorResponseOperatingRangeAssessment\n): void {\n const evaluated =\n operatingRange\n .evaluatedSpectralNodeInputs;\n\n if (\n evaluated === undefined ||\n evaluated.length !== nodes.length\n ) {\n throw new InvalidScientificInputError(\n \"operatingRange must carry one evaluated spectral-node input per reduction wavelength node.\"\n );\n }\n\n if (\n operatingRange\n .evaluatedWavelengthRangeNanometers\n .minimum !==\n reduction.wavelengthRangeNanometers\n .minimum ||\n operatingRange\n .evaluatedWavelengthRangeNanometers\n .maximum !==\n reduction.wavelengthRangeNanometers\n .maximum\n ) {\n throw new InvalidScientificInputError(\n \"operatingRange wavelength range must exactly match the reduction.\"\n );\n }\n\n evaluated.forEach(\n (entry, index) => {\n const node = nodes[index]!;\n if (\n entry.spectralSampleIndex !==\n node.spectralSampleIndex ||\n entry.wavelengthNanometers !==\n node.wavelengthNanometers ||\n entry.wavelengthMeasureNanometers !==\n node.wavelengthMeasureNanometers\n ) {\n throw new InvalidScientificInputError(\n \"operatingRange spectral-node identities must exactly match the reduction.\"\n );\n }\n\n const expected =\n operatingRange.inputRange.kind ===\n \"wavelength-integrated-geometric-aperture-radiant-power\"\n ? node\n .wavelengthIntegratedGeometricApertureIncidentFluxContributionWatts\n : node\n .wavelengthIntegratedSpatialAverageContributionWattsPerSquareMeter;\n\n if (\n entry.kind !==\n operatingRange.inputRange.kind ||\n entry.unit !==\n operatingRange.inputRange.unit ||\n !approximatelyEqual(\n entry.value,\n expected\n )\n ) {\n throw new InvalidScientificInputError(\n \"operatingRange spectral-node values must match the reduction values in the calibrated input domain.\"\n );\n }\n }\n );\n}\n\nfunction validateResponseBinding(\n resolved:\n ResolvedSensorSpectralResponse,\n reduction:\n SensorSpatioSpectralIrradianceReduction\n): void {\n if (\n resolved.profileId !==\n reduction.responseProfileId ||\n resolved.colorSamplingProfileId !==\n reduction.colorSamplingProfileId ||\n resolved.channelId !==\n reduction.channelId ||\n resolved.sourceResponseKind !==\n reduction.sourceResponseKind ||\n resolved.responseScope !==\n reduction.responseScope ||\n resolved.scientificStatus !==\n reduction.responseScientificStatus ||\n canonicalJson(\n resolved.uncertainty\n ) !==\n canonicalJson(\n reduction.responseUncertainty\n ) ||\n canonicalJson(\n resolved.componentEvidence\n ) !==\n canonicalJson({\n profile:\n reduction.componentEvidence\n .spectral.profile,\n channel:\n reduction.componentEvidence\n .spectral.channel,\n curves:\n reduction.componentEvidence\n .spectral.curves\n })\n ) {\n throw new InvalidScientificInputError(\n \"Resolved A/W response calibration metadata/evidence must exactly match the reduction.\"\n );\n }\n}\n\nfunction validateExactResponseDataBinding(\n responseProfile:\n SensorSpectralResponseProfile,\n reduction:\n SensorSpatioSpectralIrradianceReduction\n): void {\n const response =\n responseProfile.channels.find(\n (entry) =>\n entry.channelId ===\n reduction.channelId\n );\n if (reduction.responseChannelBinding !== undefined) {\n requireCurrentSensorSpectralResponseChannelBinding(\n reduction.responseChannelBinding\n );\n }\n if (\n response === undefined ||\n reduction.responseChannelBinding ===\n undefined ||\n canonicalJson(\n createSensorSpectralResponseChannelBinding(\n response\n )\n ) !==\n canonicalJson(\n reduction.responseChannelBinding\n )\n ) {\n throw new InvalidScientificInputError(\n \"Supplied spectral response channel data must exactly match the response-channel binding carried by the reduction.\"\n );\n }\n}\n\nfunction validateElectricalBinding(\n profile:\n SensorResponsivityElectricalApplicabilityProfile,\n input:\n CalculateSensorResponsivityPhotocurrentInput,\n operatingElectricalConditions:\n SensorResponsivityElectricalConditions\n): {\n compatibility:\n \"exact-match\" |\n \"assumed-compatible\";\n assumptionEvidence:\n readonly EvidenceProvenance[];\n} {\n if (\n profile.responseApplicationProfileId !==\n input.compatibility\n .applicationProfileId ||\n profile.spectralResponseProfileId !==\n input.reduction\n .responseProfileId ||\n profile.colorSamplingProfileId !==\n input.reduction\n .colorSamplingProfileId ||\n profile.channelId !==\n input.reduction.channelId\n ) {\n throw new InvalidScientificInputError(\n \"Electrical applicability profile identities must exactly match the response pipeline.\"\n );\n }\n\n if (\n profile.conditionPolicy.kind ===\n \"exact-match-required\"\n ) {\n if (\n !electricalConditionsMatch(\n profile.referenceConditions,\n operatingElectricalConditions\n )\n ) {\n throw new InvalidScientificInputError(\n \"Operating electrical conditions must exactly match the A/W calibration reference conditions.\"\n );\n }\n return {\n compatibility: \"exact-match\",\n assumptionEvidence: []\n };\n }\n\n return {\n compatibility:\n \"assumed-compatible\",\n assumptionEvidence:\n profile.conditionPolicy.evidence\n };\n}\n\n/**\n * Sums responsivity (A/W) × radiant power over wavelength bins to get the steady current magnitude,\n * under explicit electrical conditions.\n *\n * This is not EQE, an electron rate, a transimpedance voltage or RAW. Fast-changing current needs a\n * separate time-dependent detector model.\n * @param input - The input; see `CalculateSensorResponsivityPhotocurrentInput` for its fields, units and coordinates.\n * @returns The result. Success does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the package export and its full type definitions.\n */\nexport function calculateSensorResponsivityPhotocurrent(\n input:\n CalculateSensorResponsivityPhotocurrentInput\n): CalculationResult<SensorResponsivityPhotocurrent> {\n requireInputKeys(input, \"calculateSensorResponsivityPhotocurrent\", [\"reduction\", \"compatibility\", \"operatingRange\", \"colorSamplingProfile\", \"spectralResponseProfile\", \"electricalApplicabilityProfile\", \"operatingElectricalConditions\"]);\n validateAuthorizationChain(\n input.reduction,\n input.compatibility,\n input.operatingRange\n );\n\n if (\n input.reduction\n .sourceResponseKind !==\n \"effective-spectral-responsivity\"\n ) {\n throw new InvalidScientificInputError(\n \"A/W photocurrent conversion requires effective spectral responsivity, not EQE.\"\n );\n }\n\n const colorProfile =\n parseSensorColorSamplingProfile(\n input.colorSamplingProfile\n );\n const responseProfile =\n parseSensorSpectralResponseProfile(\n input.spectralResponseProfile\n );\n const electricalProfile =\n parseSensorResponsivityElectricalApplicabilityProfile(\n input.electricalApplicabilityProfile\n );\n\n if (\n colorProfile.profileId !==\n input.reduction\n .colorSamplingProfileId ||\n responseProfile.profileId !==\n input.reduction\n .responseProfileId ||\n responseProfile\n .colorSamplingProfileId !==\n colorProfile.profileId\n ) {\n throw new InvalidScientificInputError(\n \"Supplied color/spectral response profiles must exactly match the reduction identities.\"\n );\n }\n\n validateExactResponseDataBinding(\n responseProfile,\n input.reduction\n );\n\n const operatingElectricalConditions =\n parseElectricalConditions(\n input.operatingElectricalConditions,\n \"operatingElectricalConditions\"\n );\n const electrical =\n validateElectricalBinding(\n electricalProfile,\n input,\n operatingElectricalConditions\n );\n const nodes =\n validateReductionNodes(\n input.reduction\n );\n validateOperatingRangeNodeBinding(\n input.reduction,\n nodes,\n input.operatingRange\n );\n\n const currentSum:\n CompensatedSum = {\n sum: 0,\n correction: 0\n };\n const perWavelength:\n SensorResponsivityWavelengthCurrentContribution[] =\n [];\n let responseBindingValidated =\n false;\n\n for (const node of nodes) {\n const resolved =\n resolveParsedSensorSpectralResponseAtWavelength({\n colorSamplingProfile:\n colorProfile,\n spectralResponseProfile:\n responseProfile,\n channelId:\n input.reduction.channelId,\n wavelengthNanometers:\n node.wavelengthNanometers,\n wavelengthBasis:\n input.reduction\n .wavelengthBasis\n });\n\n if (!responseBindingValidated) {\n validateResponseBinding(\n resolved.value,\n input.reduction\n );\n responseBindingValidated =\n true;\n }\n\n const responsivity =\n resolved.value.response as Extract<\n typeof resolved.value.response,\n {\n kind:\n \"effective-spectral-responsivity\";\n }\n >;\n\n const radiantPowerContributionWatts =\n node\n .geometricApertureIncidentSpectralFluxWattsPerNanometer *\n node.wavelengthMeasureNanometers;\n const photocurrentMagnitudeContributionAmperes =\n radiantPowerContributionWatts *\n responsivity.amperesPerWatt;\n\n if (\n !Number.isFinite(\n radiantPowerContributionWatts\n ) ||\n !Number.isFinite(\n photocurrentMagnitudeContributionAmperes\n ) ||\n photocurrentMagnitudeContributionAmperes <\n 0\n ) {\n throw new InvalidScientificInputError(\n \"A/W wavelength-node photocurrent calculation must remain finite and nonnegative.\"\n );\n }\n\n addCompensated(\n currentSum,\n photocurrentMagnitudeContributionAmperes\n );\n\n perWavelength.push({\n spectralSampleIndex:\n node.spectralSampleIndex,\n wavelengthNanometers:\n node.wavelengthNanometers,\n wavelengthMeasureNanometers:\n node.wavelengthMeasureNanometers,\n geometricApertureIncidentSpectralFluxWattsPerNanometer:\n node\n .geometricApertureIncidentSpectralFluxWattsPerNanometer,\n radiantPowerContributionWatts,\n spectralResponsivityAmperesPerWatt:\n responsivity.amperesPerWatt,\n responseInterpolationUsed:\n resolved.value\n .interpolationUsed,\n photocurrentMagnitudeContributionAmperes\n });\n }\n\n if (\n !Number.isFinite(\n currentSum.sum\n ) ||\n currentSum.sum < 0\n ) {\n throw new InvalidScientificInputError(\n \"Total A/W photocurrent magnitude must remain finite and nonnegative.\"\n );\n }\n\n return approximationResult(\n {\n colorSamplingProfileId:\n input.reduction\n .colorSamplingProfileId,\n responseProfileId:\n input.reduction\n .responseProfileId,\n responseApplicationProfileId:\n input.compatibility\n .applicationProfileId,\n operatingRangeProfileId:\n input.operatingRange\n .operatingRangeProfileId,\n electricalApplicabilityProfileId:\n electricalProfile.profileId,\n site: {\n ...input.reduction.site\n },\n channelId:\n input.reduction.channelId,\n sourceResponseKind:\n \"effective-spectral-responsivity\",\n responseScope:\n input.reduction.responseScope,\n responseReferencePlane:\n input.compatibility\n .requiredSourcePlane,\n wavelengthBasis:\n input.reduction\n .wavelengthBasis,\n wavelengthRangeNanometers: {\n ...input.reduction\n .wavelengthRangeNanometers\n },\n electricalReferenceConditions:\n electricalProfile\n .referenceConditions,\n operatingElectricalConditions,\n electricalConditionPolicy:\n electricalProfile\n .conditionPolicy,\n electricalCompatibility:\n electrical.compatibility,\n spectralNodeCount:\n nodes.length,\n perWavelength,\n photocurrentMagnitudeAmperes:\n currentSum.sum,\n currentSignConvention:\n \"magnitude-only-no-circuit-polarity\",\n summationMethod:\n \"kahan-compensated\",\n responseApplicationPerformed:\n true,\n spectralResponsivityApplied:\n true,\n quantumEfficiencyApplied:\n false,\n photonRateCalculated: false,\n electronRateCalculated: false,\n currentCalculated: true,\n chargeCalculated: false,\n temporalResponseModel:\n \"quasi-static-steady-state-only\",\n detectorBandwidthModeled: false,\n transimpedanceGainApplied:\n false,\n voltageCalculated: false,\n temporalIntegrationApplied:\n false,\n exposureDurationApplied: false,\n saturationAssessed: false,\n readoutElectronicsLinearityAssessed:\n false,\n shotNoiseApplied: false,\n readNoiseApplied: false,\n adcQuantizationApplied:\n false,\n rawCodeValueProduced: false,\n responseUncertaintyPropagated:\n false,\n electricalApplicabilityUncertaintyPropagated:\n false,\n quadratureConvergenceErrorEstimated:\n false,\n componentEvidence: {\n electricalApplicability:\n electricalProfile.evidence,\n electricalConditionAssumption:\n electrical\n .assumptionEvidence\n }\n },\n \"sensor-spectral-responsivity-photocurrent\",\n \"1.0.0\",\n [\n \"Spectral responsivity in A/W is applied independently at every wavelength quadrature node as detector-terminal photocurrent magnitude per incident radiant power.\",\n \"Current sign/polarity is deliberately not modeled; the result is a nonnegative photocurrent magnitude and does not imply a circuit current direction.\",\n \"The A/W calibration is bound to explicit detector electrical conditions. Exact-match mode requires identical bias and readout-load semantics; approximation mode requires evidence and a stated limitation.\",\n \"Virtual-ground current readout and finite input impedance are modeled as calibration-condition identities only; this function does not simulate amplifier circuits or prove impedance adequacy.\",\n \"NIST photodiode guidance shows detector/electronics/loading can affect linear operation, so transimpedance/current-readout conditions are not treated as scientifically inert.\",\n \"Structural compatibility, geometric-aperture linear superposition and per-spectral-bin operating-range applicability must already authorize the radiant-power→current path.\",\n \"Response metadata/evidence and operating-range spectral-node values are rebound to the exact reduction so matching IDs alone or stale authorization cannot enable conversion.\",\n \"The calculation does not use photon energy, QE, photon rate or electron rate. A/W remains a distinct current-domain response representation.\",\n \"No transimpedance gain or voltage conversion is performed; current-to-voltage converter gain/offset/linearity remain downstream electronics contracts.\",\n \"The A/W response is used only as a quasi-static steady-state power→current mapping. Detector impulse response, bandwidth, modulation-frequency response and transient settling are not modeled.\",\n \"Outputs are instantaneous current only. Exposure-time integration to charge, saturation, noise, ADC/RAW conversion and reconstruction remain downstream.\",\n \"Response/electrical uncertainties and quadrature convergence error are not propagated into a combined current uncertainty by this version.\"\n ]\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"responsivity-photocurrent.js","sourceRoot":"","sources":["../../src/sensor/responsivity-photocurrent.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;GAUG;AAEH,OAAO,EACL,mBAAmB,EAEpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EACL,iBAAiB,EAElB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EACL,+BAA+B,EAEhC,MAAM,qBAAqB,CAAC;AAO7B,OAAO,EACL,0CAA0C,EAC1C,kDAAkD,EAClD,kCAAkC,EAClC,+CAA+C,EAKhD,MAAM,wBAAwB,CAAC;AAKhC,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,mBAAmB,IAAI,aAAa,EAAE,mBAAmB,IAAI,qBAAqB,EAAE,2BAA2B,IAAI,kCAAkC,EAAE,6BAA6B,IAAI,6BAA6B,EAAE,0BAA0B,IAAI,0BAA0B,EAAE,kCAAkC,IAAI,6BAA6B,EAAE,MAAM,8BAA8B,CAAC;AACtc,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,6BAA6B,IAAI,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAChH,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAuKjE,SAAS,yBAAyB,CAChC,KAAc,EACd,IAAY;IAEZ,MAAM,MAAM,GAAG,aAAa,CAC1B,KAAK,EACL,IAAI,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,CAC9B,CAAC;IACF,MAAM,IAAI,GAAG,aAAa,CACxB,MAAM,CAAC,IAAI,EACX,IAAI,GAAG,OAAO,EAAE,IAAI,CACrB,CAAC;IACF,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,wBAAwB,EAAE,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,EAAE,IAAI,GAAG,OAAO,CAAC,CAAC;IAC/I,MAAM,WAAW,GAAG,aAAa,CAC/B,MAAM,CAAC,WAAW,EAClB,IAAI,GAAG,cAAc,EAAE,IAAI,CAC5B,CAAC;IACF,0BAA0B,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,gCAAgC,EAAE,CAAC,MAAM,CAAC,EAAE,wBAAwB,EAAE,CAAC,MAAM,EAAE,oBAAoB,CAAC,EAAE,EAAE,IAAI,GAAG,cAAc,CAAC,CAAC;IAEjL,MAAM,UAAU,GAEZ,IAAI,CAAC,IAAI;QACT,wBAAwB;QACtB,CAAC,CAAC;YACE,IAAI,EACF,wBAAwB;SAC3B;QACH,CAAC,CAAC,IAAI,CAAC,IAAI;YACT,gBAAgB;YAChB,CAAC,CAAC;gBACE,IAAI,EACF,gBAAgB;gBAClB,cAAc,EACZ,kCAAkC,CAChC,IAAI,CAAC,cAAc,EACnB,IAAI;oBACF,sBAAsB,CACzB;aACJ;YACH,CAAC,CAAC,CAAC,GAAU,EAAE;gBACX,MAAM,IAAI,yBAAyB,CACjC,IAAI;oBACF,wBAAwB,CAC3B,CAAC;YACJ,CAAC,CAAC,EAAE,CAAC;IAEf,MAAM,aAAa,GAEf,WAAW,CAAC,IAAI;QAChB,gCAAgC;QAC9B,CAAC,CAAC;YACE,IAAI,EACF,gCAAgC;SACnC;QACH,CAAC,CAAC,WAAW,CAAC,IAAI;YAChB,wBAAwB;YACxB,CAAC,CAAC;gBACE,IAAI,EACF,wBAAwB;gBAC1B,kBAAkB,EAChB,kCAAkC,CAChC,WAAW;qBACR,kBAAkB,EACrB,IAAI;oBACF,iCAAiC,CACpC;aACJ;YACH,CAAC,CAAC,CAAC,GAAU,EAAE;gBACX,MAAM,IAAI,yBAAyB,CACjC,IAAI;oBACF,+BAA+B,CAClC,CAAC;YACJ,CAAC,CAAC,EAAE,CAAC;IAEf,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,aAAa;KAC3B,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,qDAAqD,CACnE,KAAc;IAEd,MAAM,MAAM,GAAG,aAAa,CAC1B,KAAK,EACL,2CAA2C,EAAE,CAAC,eAAe,EAAE,eAAe,EAAE,kBAAkB,EAAE,aAAa,EAAE,WAAW,EAAE,8BAA8B,EAAE,2BAA2B,EAAE,wBAAwB,EAAE,WAAW,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,UAAU,CAAC,CAC1R,CAAC;IAEF,IACE,MAAM,CAAC,aAAa,KAAK,OAAO,EAChC,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,0EAA0E,CAC3E,CAAC;IACJ,CAAC;IACD,IACE,MAAM,CAAC,aAAa;QACpB,0CAA0C,EAC1C,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,qEAAqE,CACtE,CAAC;IACJ,CAAC;IACD,IACE,MAAM,CAAC,gBAAgB;QACrB,YAAY;QACd,MAAM,CAAC,gBAAgB;YACrB,eAAe,EACjB,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,wEAAwE,CACzE,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GACf,gBAAgB,CACd,MAAM,CAAC,WAAW,EAClB,uDAAuD,CACxD,CAAC;IAEJ,IACE,MAAM,CAAC,gBAAgB;QACrB,YAAY;QACd,WAAW,CAAC,IAAI;YACd,gBAAgB,EAClB,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,6FAA6F,CAC9F,CAAC;IACJ,CAAC;IAED,OAAO;QACL,aAAa,EAAE,OAAO;QACtB,SAAS,EACP,qBAAqB,CACnB,MAAM,CAAC,SAAS,EAChB,qDAAqD,CACtD;QACH,4BAA4B,EAC1B,qBAAqB,CACnB,MAAM;aACH,4BAA4B,EAC/B,wEAAwE,CACzE;QACH,yBAAyB,EACvB,qBAAqB,CACnB,MAAM;aACH,yBAAyB,EAC5B,qEAAqE,CACtE;QACH,sBAAsB,EACpB,qBAAqB,CACnB,MAAM,CAAC,sBAAsB,EAC7B,kEAAkE,CACnE;QACH,SAAS,EACP,qBAAqB,CACnB,MAAM,CAAC,SAAS,EAChB,qDAAqD,CACtD;QACH,aAAa,EACX,0CAA0C;QAC5C,mBAAmB,EACjB,yBAAyB,CACvB,MAAM,CAAC,mBAAmB,EAC1B,+DAA+D,CAChE;QACH,eAAe,EACb,oBAAoB,CAClB,MAAM,CAAC,eAAe,EACtB,2DAA2D,CAC5D;QACH,gBAAgB,EACd,MAAM,CAAC,gBAAgB;QACzB,WAAW;QACX,QAAQ,EACN,iBAAiB,CACf,MAAM,CAAC,QAAQ,EACf,oDAAoD,CACrD;KACJ,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CACpB,KAAc;IAEd,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,WAAW,CAAC;IAC5C,OAAO,sBAAsB,CAAC,KAAK,EAAE;QACnC,yBAAyB,EAAE,MAAM;QACjC,sBAAsB,EACpB,6DAA6D;QAC/D,uBAAuB,EACrB,yDAAyD;KAC5D,CAAC,CAAC;AACL,CAAC;AAGD,SAAS,yBAAyB,CAChC,SACwC,EACxC,SACwC;IAExC,OAAO,CACL,aAAa,CAAC,SAAS,CAAC;QACxB,aAAa,CAAC,SAAS,CAAC,CACzB,CAAC;AACJ,CAAC;AAED,SAAS,0BAA0B,CACjC,SACyC,EACzC,aACkD,EAClD,cACwC;IAExC,kBAAkB,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;IACjD,IACE,SAAS,CAAC,aAAa;QACrB,oDAAoD;QACtD,SAAS;aACN,oCAAoC;YACrC,KAAK;QACP,SAAS;aACN,2BAA2B;YAC5B,KAAK;QACP,SAAS,CAAC,0BAA0B;YAClC,KAAK,EACP,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,yFAAyF,CAC1F,CAAC;IACJ,CAAC;IAED,IACE,CAAC,aAAa;SACX,kCAAkC;QACrC,aAAa,CAAC,mBAAmB;YAC/B,SAAS;QACX,aAAa,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QACnC,CAAC,aAAa,CAAC,kBAAkB;QACjC,aAAa,CAAC,kBAAkB;YAC9B,0BAA0B,EAC5B,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,oFAAoF,CACrF,CAAC;IACJ,CAAC;IAED,IACE,aAAa;SACV,yBAAyB;QAC1B,SAAS,CAAC,iBAAiB;QAC7B,aAAa,CAAC,sBAAsB;YAClC,SAAS,CAAC,sBAAsB;QAClC,aAAa,CAAC,SAAS;YACrB,SAAS,CAAC,SAAS;QACrB,aAAa,CAAC,aAAa;YACzB,SAAS,CAAC,aAAa,EACzB,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,4DAA4D,CAC7D,CAAC;IACJ,CAAC;IAED,IACE,CAAC,cAAc;SACZ,mCAAmC;QACtC,CAAC,cAAc;aACZ,oCAAoC;QACvC,CAAC,cAAc;aACZ,gCAAgC;QACnC,cAAc,CAAC,MAAM,KAAK,SAAS;QACnC,cAAc,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QACpC,cAAc,CAAC,kBAAkB;YAC/B,0BAA0B;QAC5B,cAAc;aACX,4BAA4B;YAC7B,KAAK;QACP,cAAc;aACX,0BAA0B,KAAK,KAAK;QACvC,cAAc;aACX,6BAA6B,KAAK,KAAK;QAC1C,CAAC,cAAc;aACZ,sCAAsC;QACzC,cAAc;aACX,kBAAkB,CAAC,IAAI;YACxB,kBAAkB;QACpB,cAAc;aACX,qBAAqB,CAAC,IAAI;YAC3B,8CAA8C,EAChD,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,8EAA8E,CAC/E,CAAC;IACJ,CAAC;IAED,IACE,cAAc;SACX,yBAAyB;QAC1B,SAAS,CAAC,iBAAiB;QAC7B,cAAc;aACX,sBAAsB;YACvB,SAAS,CAAC,sBAAsB;QAClC,cAAc,CAAC,SAAS;YACtB,SAAS,CAAC,SAAS;QACrB,cAAc;aACX,4BAA4B;YAC7B,aAAa,CAAC,oBAAoB,EACpC,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,0FAA0F,CAC3F,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAC7B,SACyC;IAEzC,IACE,CAAC,KAAK,CAAC,OAAO,CACZ,SAAS,CAAC,aAAa,CACxB;QACD,CAAC,MAAM,CAAC,aAAa,CACnB,SAAS,CAAC,iBAAiB,CAC5B;QACD,SAAS,CAAC,iBAAiB,IAAI,CAAC;QAChC,SAAS,CAAC,aAAa,CAAC,MAAM;YAC5B,SAAS,CAAC,iBAAiB,EAC7B,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,yEAAyE,CAC1E,CAAC;IACJ,CAAC;IAED,IAAI,eAAe,GACjB,MAAM,CAAC,iBAAiB,CAAC;IAC3B,IAAI,mBAAmB,GAAG,CAAC,CAAC;IAC5B,MAAM,UAAU,GACG;QACf,GAAG,EAAE,CAAC;QACN,UAAU,EAAE,CAAC;KACd,CAAC;IAEJ,SAAS,CAAC,aAAa,CAAC,OAAO,CAC7B,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE;QACnB,MAAM,WAAW,GACf,6BAA6B,CAC3B,IAAI,CAAC,mBAAmB,EACxB,0BAA0B;YACxB,UAAU;YACV,uBAAuB,CAC1B,CAAC;QACJ,IAAI,WAAW,KAAK,UAAU,EAAE,CAAC;YAC/B,MAAM,IAAI,2BAA2B,CACnC,mGAAmG,CACpG,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GACd,0BAA0B,CACxB,IAAI,CAAC,oBAAoB,EACzB,0BAA0B;YACxB,UAAU;YACV,wBAAwB,CAC3B,CAAC;QACJ,IACE,UAAU,IAAI,eAAe,EAC7B,CAAC;YACD,MAAM,IAAI,2BAA2B,CACnC,yDAAyD,CAC1D,CAAC;QACJ,CAAC;QACD,eAAe,GAAG,UAAU,CAAC;QAE7B,MAAM,OAAO,GACX,0BAA0B,CACxB,IAAI,CAAC,2BAA2B,EAChC,0BAA0B;YACxB,UAAU;YACV,+BAA+B,CAClC,CAAC;QACJ,MAAM,gBAAgB,GACpB,0BAA0B,CACxB,IAAI,CAAC,0BAA0B,EAC/B,0BAA0B;YACxB,UAAU;YACV,8BAA8B,CACjC,CAAC;QACJ,MAAM,WAAW,GACf,6BAA6B,CAC3B,IAAI;aACD,sDAAsD,EACzD,0BAA0B;YACxB,UAAU;YACV,0DAA0D,CAC7D,CAAC;QACJ,MAAM,KAAK,GACT,6BAA6B,CAC3B,IAAI;aACD,kEAAkE,EACrE,0BAA0B;YACxB,UAAU;YACV,sEAAsE,CACzE,CAAC;QACJ,MAAM,QAAQ,GACZ,WAAW,GAAG,OAAO,CAAC;QACxB,IACE,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAC1B,CAAC,kBAAkB,CACjB,KAAK,EACL,QAAQ,CACT,EACD,CAAC;YACD,MAAM,IAAI,2BAA2B,CACnC,kGAAkG,CACnG,CAAC;QACJ,CAAC;QAED,mBAAmB;YACjB,gBAAgB,CAAC;QACnB,cAAc,CACZ,UAAU,EACV,KAAK,CACN,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,IACE,CAAC,MAAM,CAAC,QAAQ,CACd,mBAAmB,CACpB;QACD,CAAC,kBAAkB,CACjB,mBAAmB,EACnB,CAAC,CACF,EACD,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,wDAAwD,CACzD,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,GAClB,6BAA6B,CAC3B,SAAS;SACN,sDAAsD,EACzD,kEAAkE,CACnE,CAAC;IACJ,IACE,CAAC,kBAAkB,CACjB,UAAU,CAAC,GAAG,EACd,cAAc,CACf,EACD,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,qFAAqF,CACtF,CAAC;IACJ,CAAC;IAED,OAAO,SAAS,CAAC,aAAa,CAAC;AACjC,CAAC;AAED,SAAS,iCAAiC,CACxC,SACyC,EACzC,KACoD,EACpD,cACwC;IAExC,MAAM,SAAS,GACb,cAAc;SACX,2BAA2B,CAAC;IAEjC,IACE,SAAS,KAAK,SAAS;QACvB,SAAS,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EACjC,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,4FAA4F,CAC7F,CAAC;IACJ,CAAC;IAED,IACE,cAAc;SACX,kCAAkC;SAClC,OAAO;QACR,SAAS,CAAC,yBAAyB;aAChC,OAAO;QACZ,cAAc;aACX,kCAAkC;aAClC,OAAO;YACR,SAAS,CAAC,yBAAyB;iBAChC,OAAO,EACZ,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,mEAAmE,CACpE,CAAC;IACJ,CAAC;IAED,SAAS,CAAC,OAAO,CACf,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACf,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAE,CAAC;QAC3B,IACE,KAAK,CAAC,mBAAmB;YACvB,IAAI,CAAC,mBAAmB;YAC1B,KAAK,CAAC,oBAAoB;gBACxB,IAAI,CAAC,oBAAoB;YAC3B,KAAK,CAAC,2BAA2B;gBAC/B,IAAI,CAAC,2BAA2B,EAClC,CAAC;YACD,MAAM,IAAI,2BAA2B,CACnC,2EAA2E,CAC5E,CAAC;QACJ,CAAC;QAED,MAAM,QAAQ,GACZ,cAAc,CAAC,UAAU,CAAC,IAAI;YAC5B,wDAAwD;YACxD,CAAC,CAAC,IAAI;iBACD,kEAAkE;YACvE,CAAC,CAAC,IAAI;iBACD,iEAAiE,CAAC;QAE3E,IACE,KAAK,CAAC,IAAI;YACR,cAAc,CAAC,UAAU,CAAC,IAAI;YAChC,KAAK,CAAC,IAAI;gBACR,cAAc,CAAC,UAAU,CAAC,IAAI;YAChC,CAAC,kBAAkB,CACjB,KAAK,CAAC,KAAK,EACX,QAAQ,CACT,EACD,CAAC;YACD,MAAM,IAAI,2BAA2B,CACnC,qGAAqG,CACtG,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAC9B,QACgC,EAChC,SACyC;IAEzC,IACE,QAAQ,CAAC,SAAS;QAChB,SAAS,CAAC,iBAAiB;QAC7B,QAAQ,CAAC,sBAAsB;YAC7B,SAAS,CAAC,sBAAsB;QAClC,QAAQ,CAAC,SAAS;YAChB,SAAS,CAAC,SAAS;QACrB,QAAQ,CAAC,kBAAkB;YACzB,SAAS,CAAC,kBAAkB;QAC9B,QAAQ,CAAC,aAAa;YACpB,SAAS,CAAC,aAAa;QACzB,QAAQ,CAAC,gBAAgB;YACvB,SAAS,CAAC,wBAAwB;QACpC,aAAa,CACX,QAAQ,CAAC,WAAW,CACrB;YACC,aAAa,CACX,SAAS,CAAC,mBAAmB,CAC9B;QACH,aAAa,CACX,QAAQ,CAAC,iBAAiB,CAC3B;YACC,aAAa,CAAC;gBACZ,OAAO,EACL,SAAS,CAAC,iBAAiB;qBACxB,QAAQ,CAAC,OAAO;gBACrB,OAAO,EACL,SAAS,CAAC,iBAAiB;qBACxB,QAAQ,CAAC,OAAO;gBACrB,MAAM,EACJ,SAAS,CAAC,iBAAiB;qBACxB,QAAQ,CAAC,MAAM;aACrB,CAAC,EACJ,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,uFAAuF,CACxF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,gCAAgC,CACvC,eAC+B,EAC/B,SACyC;IAEzC,MAAM,QAAQ,GACZ,eAAe,CAAC,QAAQ,CAAC,IAAI,CAC3B,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,SAAS;QACf,SAAS,CAAC,SAAS,CACtB,CAAC;IACJ,IAAI,SAAS,CAAC,sBAAsB,KAAK,SAAS,EAAE,CAAC;QACnD,kDAAkD,CAChD,SAAS,CAAC,sBAAsB,CACjC,CAAC;IACJ,CAAC;IACD,IACE,QAAQ,KAAK,SAAS;QACtB,SAAS,CAAC,sBAAsB;YAC9B,SAAS;QACX,aAAa,CACX,0CAA0C,CACxC,QAAQ,CACT,CACF;YACC,aAAa,CACX,SAAS,CAAC,sBAAsB,CACjC,EACH,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,mHAAmH,CACpH,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,yBAAyB,CAChC,OACkD,EAClD,KAC8C,EAC9C,6BACwC;IAQxC,IACE,OAAO,CAAC,4BAA4B;QAClC,KAAK,CAAC,aAAa;aAChB,oBAAoB;QACzB,OAAO,CAAC,yBAAyB;YAC/B,KAAK,CAAC,SAAS;iBACZ,iBAAiB;QACtB,OAAO,CAAC,sBAAsB;YAC5B,KAAK,CAAC,SAAS;iBACZ,sBAAsB;QAC3B,OAAO,CAAC,SAAS;YACf,KAAK,CAAC,SAAS,CAAC,SAAS,EAC3B,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,uFAAuF,CACxF,CAAC;IACJ,CAAC;IAED,IACE,OAAO,CAAC,eAAe,CAAC,IAAI;QAC1B,sBAAsB,EACxB,CAAC;QACD,IACE,CAAC,yBAAyB,CACxB,OAAO,CAAC,mBAAmB,EAC3B,6BAA6B,CAC9B,EACD,CAAC;YACD,MAAM,IAAI,2BAA2B,CACnC,8FAA8F,CAC/F,CAAC;QACJ,CAAC;QACD,OAAO;YACL,aAAa,EAAE,aAAa;YAC5B,kBAAkB,EAAE,EAAE;SACvB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,aAAa,EACX,oBAAoB;QACtB,kBAAkB,EAChB,OAAO,CAAC,eAAe,CAAC,QAAQ;KACnC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uCAAuC,CACrD,KAC8C;IAE9C,gBAAgB,CAAC,KAAK,EAAE,yCAAyC,EAAE,CAAC,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,yBAAyB,EAAE,gCAAgC,EAAE,+BAA+B,CAAC,CAAC,CAAC;IAC3O,0BAA0B,CACxB,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,aAAa,EACnB,KAAK,CAAC,cAAc,CACrB,CAAC;IAEF,IACE,KAAK,CAAC,SAAS;SACZ,kBAAkB;QACnB,iCAAiC,EACnC,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,gFAAgF,CACjF,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAChB,+BAA+B,CAC7B,KAAK,CAAC,oBAAoB,CAC3B,CAAC;IACJ,MAAM,eAAe,GACnB,kCAAkC,CAChC,KAAK,CAAC,uBAAuB,CAC9B,CAAC;IACJ,MAAM,iBAAiB,GACrB,qDAAqD,CACnD,KAAK,CAAC,8BAA8B,CACrC,CAAC;IAEJ,IACE,YAAY,CAAC,SAAS;QACpB,KAAK,CAAC,SAAS;aACZ,sBAAsB;QAC3B,eAAe,CAAC,SAAS;YACvB,KAAK,CAAC,SAAS;iBACZ,iBAAiB;QACtB,eAAe;aACZ,sBAAsB;YACvB,YAAY,CAAC,SAAS,EACxB,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,wFAAwF,CACzF,CAAC;IACJ,CAAC;IAED,gCAAgC,CAC9B,eAAe,EACf,KAAK,CAAC,SAAS,CAChB,CAAC;IAEF,MAAM,6BAA6B,GACjC,yBAAyB,CACvB,KAAK,CAAC,6BAA6B,EACnC,+BAA+B,CAChC,CAAC;IACJ,MAAM,UAAU,GACd,yBAAyB,CACvB,iBAAiB,EACjB,KAAK,EACL,6BAA6B,CAC9B,CAAC;IACJ,MAAM,KAAK,GACT,sBAAsB,CACpB,KAAK,CAAC,SAAS,CAChB,CAAC;IACJ,iCAAiC,CAC/B,KAAK,CAAC,SAAS,EACf,KAAK,EACL,KAAK,CAAC,cAAc,CACrB,CAAC;IAEF,MAAM,UAAU,GACG;QACf,GAAG,EAAE,CAAC;QACN,UAAU,EAAE,CAAC;KACd,CAAC;IACJ,MAAM,aAAa,GAEf,EAAE,CAAC;IACP,IAAI,wBAAwB,GAC1B,KAAK,CAAC;IAER,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GACZ,+CAA+C,CAAC;YAC9C,oBAAoB,EAClB,YAAY;YACd,uBAAuB,EACrB,eAAe;YACjB,SAAS,EACP,KAAK,CAAC,SAAS,CAAC,SAAS;YAC3B,oBAAoB,EAClB,IAAI,CAAC,oBAAoB;YAC3B,eAAe,EACb,KAAK,CAAC,SAAS;iBACZ,eAAe;SACrB,CAAC,CAAC;QAEL,IAAI,CAAC,wBAAwB,EAAE,CAAC;YAC9B,uBAAuB,CACrB,QAAQ,CAAC,KAAK,EACd,KAAK,CAAC,SAAS,CAChB,CAAC;YACF,wBAAwB;gBACtB,IAAI,CAAC;QACT,CAAC;QAED,MAAM,YAAY,GAChB,QAAQ,CAAC,KAAK,CAAC,QAMd,CAAC;QAEJ,MAAM,6BAA6B,GACjC,IAAI;aACD,sDAAsD;YACzD,IAAI,CAAC,2BAA2B,CAAC;QACnC,MAAM,wCAAwC,GAC5C,6BAA6B;YAC7B,YAAY,CAAC,cAAc,CAAC;QAE9B,IACE,CAAC,MAAM,CAAC,QAAQ,CACd,6BAA6B,CAC9B;YACD,CAAC,MAAM,CAAC,QAAQ,CACd,wCAAwC,CACzC;YACD,wCAAwC;gBACtC,CAAC,EACH,CAAC;YACD,MAAM,IAAI,2BAA2B,CACnC,kFAAkF,CACnF,CAAC;QACJ,CAAC;QAED,cAAc,CACZ,UAAU,EACV,wCAAwC,CACzC,CAAC;QAEF,aAAa,CAAC,IAAI,CAAC;YACjB,mBAAmB,EACjB,IAAI,CAAC,mBAAmB;YAC1B,oBAAoB,EAClB,IAAI,CAAC,oBAAoB;YAC3B,2BAA2B,EACzB,IAAI,CAAC,2BAA2B;YAClC,sDAAsD,EACpD,IAAI;iBACD,sDAAsD;YAC3D,6BAA6B;YAC7B,kCAAkC,EAChC,YAAY,CAAC,cAAc;YAC7B,yBAAyB,EACvB,QAAQ,CAAC,KAAK;iBACX,iBAAiB;YACtB,wCAAwC;SACzC,CAAC,CAAC;IACL,CAAC;IAED,IACE,CAAC,MAAM,CAAC,QAAQ,CACd,UAAU,CAAC,GAAG,CACf;QACD,UAAU,CAAC,GAAG,GAAG,CAAC,EAClB,CAAC;QACD,MAAM,IAAI,2BAA2B,CACnC,sEAAsE,CACvE,CAAC;IACJ,CAAC;IAED,OAAO,mBAAmB,CACxB;QACE,sBAAsB,EACpB,KAAK,CAAC,SAAS;aACZ,sBAAsB;QAC3B,iBAAiB,EACf,KAAK,CAAC,SAAS;aACZ,iBAAiB;QACtB,4BAA4B,EAC1B,KAAK,CAAC,aAAa;aAChB,oBAAoB;QACzB,uBAAuB,EACrB,KAAK,CAAC,cAAc;aACjB,uBAAuB;QAC5B,gCAAgC,EAC9B,iBAAiB,CAAC,SAAS;QAC7B,IAAI,EAAE;YACJ,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI;SACxB;QACD,SAAS,EACP,KAAK,CAAC,SAAS,CAAC,SAAS;QAC3B,kBAAkB,EAChB,iCAAiC;QACnC,aAAa,EACX,KAAK,CAAC,SAAS,CAAC,aAAa;QAC/B,sBAAsB,EACpB,KAAK,CAAC,aAAa;aAChB,mBAAmB;QACxB,eAAe,EACb,KAAK,CAAC,SAAS;aACZ,eAAe;QACpB,yBAAyB,EAAE;YACzB,GAAG,KAAK,CAAC,SAAS;iBACf,yBAAyB;SAC7B;QACD,6BAA6B,EAC3B,iBAAiB;aACd,mBAAmB;QACxB,6BAA6B;QAC7B,yBAAyB,EACvB,iBAAiB;aACd,eAAe;QACpB,uBAAuB,EACrB,UAAU,CAAC,aAAa;QAC1B,iBAAiB,EACf,KAAK,CAAC,MAAM;QACd,aAAa;QACb,4BAA4B,EAC1B,UAAU,CAAC,GAAG;QAChB,qBAAqB,EACnB,oCAAoC;QACtC,eAAe,EACb,mBAAmB;QACrB,4BAA4B,EAC1B,IAAI;QACN,2BAA2B,EACzB,IAAI;QACN,wBAAwB,EACtB,KAAK;QACP,oBAAoB,EAAE,KAAK;QAC3B,sBAAsB,EAAE,KAAK;QAC7B,iBAAiB,EAAE,IAAI;QACvB,gBAAgB,EAAE,KAAK;QACvB,qBAAqB,EACnB,gCAAgC;QAClC,wBAAwB,EAAE,KAAK;QAC/B,yBAAyB,EACvB,KAAK;QACP,iBAAiB,EAAE,KAAK;QACxB,0BAA0B,EACxB,KAAK;QACP,uBAAuB,EAAE,KAAK;QAC9B,kBAAkB,EAAE,KAAK;QACzB,mCAAmC,EACjC,KAAK;QACP,gBAAgB,EAAE,KAAK;QACvB,gBAAgB,EAAE,KAAK;QACvB,sBAAsB,EACpB,KAAK;QACP,oBAAoB,EAAE,KAAK;QAC3B,6BAA6B,EAC3B,KAAK;QACP,4CAA4C,EAC1C,KAAK;QACP,mCAAmC,EACjC,KAAK;QACP,iBAAiB,EAAE;YACjB,uBAAuB,EACrB,iBAAiB,CAAC,QAAQ;YAC5B,6BAA6B,EAC3B,UAAU;iBACP,kBAAkB;SACxB;KACF,EACD,2CAA2C,EAC3C,OAAO,EACP;QACE,mKAAmK;QACnK,uJAAuJ;QACvJ,6MAA6M;QAC7M,iMAAiM;QACjM,gLAAgL;QAChL,6KAA6K;QAC7K,+KAA+K;QAC/K,8IAA8I;QAC9I,wJAAwJ;QACxJ,iMAAiM;QACjM,0JAA0J;QAC1J,4IAA4I;KAC7I,CACF,CAAC;AACJ,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Responsivity photocurrent: converts light power to detector current using responsivity in amperes\n * per watt (A/W).\n *\n * For each wavelength bin, current = responsivity × radiant power; the bins are summed. The result is\n * the steady (quasi-static) current magnitude at the detector terminals. The electrical bias and load\n * conditions under which the responsivity applies are explicit. This is not EQE, an electron rate, a\n * transimpedance voltage or RAW. Fast-changing current needs a separate time-dependent detector model.\n * @see docs/MOTION_AND_SIGNAL.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport {\n approximationResult,\n type CalculationResult\n} from \"../core/calculation-result.js\";\nimport { stringifyCanonicalJson } from \"../core/canonical-json.js\";\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 parseSensorColorSamplingProfile,\n type SensorColorSamplingProfile\n} from \"./color-sampling.js\";\nimport type {\n SensorResponseApplicationCompatibilityAssessment\n} from \"./response-application-compatibility.js\";\nimport type {\n SensorResponseOperatingRangeAssessment\n} from \"./response-operating-range.js\";\nimport {\n createSensorSpectralResponseChannelBinding,\n requireCurrentSensorSpectralResponseChannelBinding,\n parseSensorSpectralResponseProfile,\n resolveParsedSensorSpectralResponseAtWavelength,\n type ResolvedSensorSpectralResponse,\n type SensorSpectralResponseProfile,\n type SensorSpectralResponseScientificStatus,\n type SensorSpectralResponseUncertainty\n} from \"./spectral-response.js\";\nimport type {\n SensorSpatioSpectralIrradianceReduction,\n SensorSpatioSpectralWavelengthReduction\n} from \"./spatio-spectral-reduction.js\";\nimport { requireInputObject, requireInputKeys, rejectUnknownVariantFields, requireConfigRecord as requireRecord, requireConfigString as requireNonEmptyString, requireConfigPositiveFinite as requirePositiveFiniteConfiguration, requireInputNonNegativeFinite as requireNonNegativeFiniteInput, requireInputPositiveFinite as requirePositiveFiniteInput, requireInputNonNegativeSafeInteger as requireSafeNonNegativeInteger } from \"../core/record-validation.js\";\nimport { addCompensated, approximatelyEqual } from \"../core/shared-helpers.js\";\nimport { parseReferenceConditionPolicy as parseConditionPolicy } from \"./response-application-compatibility.js\";\nimport { parseUncertainty } from \"./response-operating-range.js\";\n\n\nexport type SensorResponsivityBiasCondition =\n | {\n kind: \"zero-bias-photovoltaic\";\n }\n | {\n kind: \"reverse-biased\";\n magnitudeVolts: number;\n };\n\nexport type SensorResponsivityReadoutLoadCondition =\n | {\n kind: \"virtual-ground-current-readout\";\n }\n | {\n kind: \"finite-input-impedance\";\n inputImpedanceOhms: number;\n };\n\nexport interface SensorResponsivityElectricalConditions {\n bias: SensorResponsivityBiasCondition;\n readoutLoad:\n SensorResponsivityReadoutLoadCondition;\n}\n\nexport type SensorResponsivityElectricalConditionPolicy =\n | {\n kind: \"exact-match-required\";\n }\n | {\n kind: \"assume-compatible\";\n limitation: string;\n evidence: readonly EvidenceProvenance[];\n };\n\nexport interface SensorResponsivityElectricalApplicabilityProfile {\n schemaVersion: \"0.1.0\";\n profileId: string;\n responseApplicationProfileId: string;\n spectralResponseProfileId: string;\n colorSamplingProfileId: string;\n channelId: string;\n outputMeaning:\n \"detector-terminal-photocurrent-magnitude\";\n referenceConditions:\n SensorResponsivityElectricalConditions;\n conditionPolicy:\n SensorResponsivityElectricalConditionPolicy;\n scientificStatus:\n SensorSpectralResponseScientificStatus;\n uncertainty:\n SensorSpectralResponseUncertainty;\n evidence: readonly EvidenceProvenance[];\n}\n\nexport interface CalculateSensorResponsivityPhotocurrentInput {\n reduction:\n SensorSpatioSpectralIrradianceReduction;\n compatibility:\n SensorResponseApplicationCompatibilityAssessment;\n operatingRange:\n SensorResponseOperatingRangeAssessment;\n colorSamplingProfile:\n SensorColorSamplingProfile;\n spectralResponseProfile:\n SensorSpectralResponseProfile;\n electricalApplicabilityProfile:\n SensorResponsivityElectricalApplicabilityProfile;\n operatingElectricalConditions:\n SensorResponsivityElectricalConditions;\n}\n\nexport interface SensorResponsivityWavelengthCurrentContribution {\n spectralSampleIndex: number;\n wavelengthNanometers: number;\n wavelengthMeasureNanometers: number;\n geometricApertureIncidentSpectralFluxWattsPerNanometer:\n number;\n radiantPowerContributionWatts: number;\n spectralResponsivityAmperesPerWatt:\n number;\n responseInterpolationUsed: boolean;\n photocurrentMagnitudeContributionAmperes:\n number;\n}\n\nexport interface SensorResponsivityPhotocurrent {\n colorSamplingProfileId: string;\n responseProfileId: string;\n responseApplicationProfileId: string;\n operatingRangeProfileId: string;\n electricalApplicabilityProfileId:\n string;\n /** The exact source colour site. Results produced by the engine fill this in. */\n site?: {\n x: number;\n y: number;\n };\n channelId: string;\n sourceResponseKind:\n \"effective-spectral-responsivity\";\n responseScope:\n SensorSpatioSpectralIrradianceReduction[\"responseScope\"];\n responseReferencePlane:\n SensorResponseApplicationCompatibilityAssessment[\"requiredSourcePlane\"];\n wavelengthBasis:\n SensorSpatioSpectralIrradianceReduction[\"wavelengthBasis\"];\n wavelengthRangeNanometers:\n SensorSpatioSpectralIrradianceReduction[\"wavelengthRangeNanometers\"];\n electricalReferenceConditions:\n SensorResponsivityElectricalConditions;\n operatingElectricalConditions:\n SensorResponsivityElectricalConditions;\n electricalConditionPolicy:\n SensorResponsivityElectricalConditionPolicy;\n electricalCompatibility:\n | \"exact-match\"\n | \"assumed-compatible\";\n spectralNodeCount: number;\n perWavelength:\n readonly SensorResponsivityWavelengthCurrentContribution[];\n photocurrentMagnitudeAmperes: number;\n currentSignConvention:\n \"magnitude-only-no-circuit-polarity\";\n summationMethod:\n \"kahan-compensated\";\n responseApplicationPerformed: true;\n spectralResponsivityApplied: true;\n quantumEfficiencyApplied: false;\n photonRateCalculated: false;\n electronRateCalculated: false;\n currentCalculated: true;\n chargeCalculated: false;\n temporalResponseModel:\n \"quasi-static-steady-state-only\";\n detectorBandwidthModeled: false;\n transimpedanceGainApplied: false;\n voltageCalculated: false;\n temporalIntegrationApplied: false;\n exposureDurationApplied: false;\n saturationAssessed: false;\n readoutElectronicsLinearityAssessed:\n false;\n shotNoiseApplied: false;\n readNoiseApplied: false;\n adcQuantizationApplied: false;\n rawCodeValueProduced: false;\n responseUncertaintyPropagated: false;\n electricalApplicabilityUncertaintyPropagated:\n false;\n quadratureConvergenceErrorEstimated:\n false;\n componentEvidence: {\n electricalApplicability:\n readonly EvidenceProvenance[];\n electricalConditionAssumption:\n readonly EvidenceProvenance[];\n };\n}\n\ninterface CompensatedSum {\n sum: number;\n correction: number;\n}\n\nfunction parseElectricalConditions(\n value: unknown,\n path: string\n): SensorResponsivityElectricalConditions {\n const record = requireRecord(\n value,\n path, [\"bias\", \"readoutLoad\"]\n );\n const bias = requireRecord(\n record.bias,\n path + \".bias\", null\n );\n rejectUnknownVariantFields(bias, \"kind\", { \"zero-bias-photovoltaic\": [\"kind\"], \"reverse-biased\": [\"kind\", \"magnitudeVolts\"] }, path + \".bias\");\n const readoutLoad = requireRecord(\n record.readoutLoad,\n path + \".readoutLoad\", null\n );\n rejectUnknownVariantFields(readoutLoad, \"kind\", { \"virtual-ground-current-readout\": [\"kind\"], \"finite-input-impedance\": [\"kind\", \"inputImpedanceOhms\"] }, path + \".readoutLoad\");\n\n const parsedBias:\n SensorResponsivityBiasCondition =\n bias.kind ===\n \"zero-bias-photovoltaic\"\n ? {\n kind:\n \"zero-bias-photovoltaic\"\n }\n : bias.kind ===\n \"reverse-biased\"\n ? {\n kind:\n \"reverse-biased\",\n magnitudeVolts:\n requirePositiveFiniteConfiguration(\n bias.magnitudeVolts,\n path +\n \".bias.magnitudeVolts\"\n )\n }\n : ((): never => {\n throw new InvalidConfigurationError(\n path +\n \".bias.kind is invalid.\"\n );\n })();\n\n const parsedReadout:\n SensorResponsivityReadoutLoadCondition =\n readoutLoad.kind ===\n \"virtual-ground-current-readout\"\n ? {\n kind:\n \"virtual-ground-current-readout\"\n }\n : readoutLoad.kind ===\n \"finite-input-impedance\"\n ? {\n kind:\n \"finite-input-impedance\",\n inputImpedanceOhms:\n requirePositiveFiniteConfiguration(\n readoutLoad\n .inputImpedanceOhms,\n path +\n \".readoutLoad.inputImpedanceOhms\"\n )\n }\n : ((): never => {\n throw new InvalidConfigurationError(\n path +\n \".readoutLoad.kind is invalid.\"\n );\n })();\n\n return {\n bias: parsedBias,\n readoutLoad: parsedReadout\n };\n}\n\n/**\n * Validates untrusted input and returns it as a normalized, typed value. Unknown enum values,\n * missing required fields and inconsistent scientific data are rejected.\n *\n * The profile states the electrical bias and load conditions under which an A/W responsivity applies.\n * @param value - Untrusted data. TypeScript types alone are not validation.\n * @returns The result. Success does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the package export and its full type definitions.\n */\nexport function parseSensorResponsivityElectricalApplicabilityProfile(\n value: unknown\n): SensorResponsivityElectricalApplicabilityProfile {\n const record = requireRecord(\n value,\n \"sensorResponsivityElectricalApplicability\", [\"schemaVersion\", \"outputMeaning\", \"scientificStatus\", \"uncertainty\", \"profileId\", \"responseApplicationProfileId\", \"spectralResponseProfileId\", \"colorSamplingProfileId\", \"channelId\", \"referenceConditions\", \"conditionPolicy\", \"evidence\"]\n );\n\n if (\n record.schemaVersion !== \"0.1.0\"\n ) {\n throw new InvalidConfigurationError(\n 'sensorResponsivityElectricalApplicability.schemaVersion must be \"0.1.0\".'\n );\n }\n if (\n record.outputMeaning !==\n \"detector-terminal-photocurrent-magnitude\"\n ) {\n throw new InvalidConfigurationError(\n \"sensorResponsivityElectricalApplicability.outputMeaning is invalid.\"\n );\n }\n if (\n record.scientificStatus !==\n \"calibrated\" &&\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n \"sensorResponsivityElectricalApplicability.scientificStatus is invalid.\"\n );\n }\n\n const uncertainty =\n parseUncertainty(\n record.uncertainty,\n \"sensorResponsivityElectricalApplicability.uncertainty\"\n );\n\n if (\n record.scientificStatus ===\n \"calibrated\" &&\n uncertainty.kind ===\n \"not-quantified\"\n ) {\n throw new InvalidConfigurationError(\n \"A calibrated electrical applicability profile must declare quantified relative uncertainty.\"\n );\n }\n\n return {\n schemaVersion: \"0.1.0\",\n profileId:\n requireNonEmptyString(\n record.profileId,\n \"sensorResponsivityElectricalApplicability.profileId\"\n ),\n responseApplicationProfileId:\n requireNonEmptyString(\n record\n .responseApplicationProfileId,\n \"sensorResponsivityElectricalApplicability.responseApplicationProfileId\"\n ),\n spectralResponseProfileId:\n requireNonEmptyString(\n record\n .spectralResponseProfileId,\n \"sensorResponsivityElectricalApplicability.spectralResponseProfileId\"\n ),\n colorSamplingProfileId:\n requireNonEmptyString(\n record.colorSamplingProfileId,\n \"sensorResponsivityElectricalApplicability.colorSamplingProfileId\"\n ),\n channelId:\n requireNonEmptyString(\n record.channelId,\n \"sensorResponsivityElectricalApplicability.channelId\"\n ),\n outputMeaning:\n \"detector-terminal-photocurrent-magnitude\",\n referenceConditions:\n parseElectricalConditions(\n record.referenceConditions,\n \"sensorResponsivityElectricalApplicability.referenceConditions\"\n ),\n conditionPolicy:\n parseConditionPolicy(\n record.conditionPolicy,\n \"sensorResponsivityElectricalApplicability.conditionPolicy\"\n ),\n scientificStatus:\n record.scientificStatus,\n uncertainty,\n evidence:\n parseEvidenceList(\n record.evidence,\n \"sensorResponsivityElectricalApplicability.evidence\"\n )\n };\n}\n\n/**\n * Identity string for parsed plain data that ignores key order, so records with\n * the same content compare equal whatever order their properties were added in.\n */\nfunction canonicalJson(\n value: unknown\n): string {\n if (value === undefined) return \"undefined\";\n return stringifyCanonicalJson(value, {\n undefinedObjectProperties: \"omit\",\n nonFiniteNumberMessage:\n \"A/W photocurrent identity data must contain finite numbers.\",\n unsupportedValueMessage:\n \"A/W photocurrent identity data must be plain JSON data.\"\n });\n}\n\n\nfunction electricalConditionsMatch(\n reference:\n SensorResponsivityElectricalConditions,\n operating:\n SensorResponsivityElectricalConditions\n): boolean {\n return (\n canonicalJson(reference) ===\n canonicalJson(operating)\n );\n}\n\nfunction validateAuthorizationChain(\n reduction:\n SensorSpatioSpectralIrradianceReduction,\n compatibility:\n SensorResponseApplicationCompatibilityAssessment,\n operatingRange:\n SensorResponseOperatingRangeAssessment\n): void {\n requireInputObject(reduction, \"reduction input\");\n if (\n reduction.outputMeaning !==\n \"pre-response-spatio-spectral-radiometric-reduction\" ||\n reduction\n .spectralResponseApplicationPerformed !==\n false ||\n reduction\n .spectralResponsivityApplied !==\n false ||\n reduction.temporalIntegrationApplied !==\n false\n ) {\n throw new InvalidScientificInputError(\n \"reduction must remain pre-response and pre-temporal before A/W photocurrent conversion.\"\n );\n }\n\n if (\n !compatibility\n .structuralCompatibilityEstablished ||\n compatibility.compatibilityStatus ===\n \"blocked\" ||\n compatibility.blockers.length !== 0 ||\n !compatibility.sourcePlaneMatched ||\n compatibility.requiredSignalPath !==\n \"radiant-power-to-current\"\n ) {\n throw new InvalidScientificInputError(\n \"compatibility must establish a non-blocked radiant-power-to-current response path.\"\n );\n }\n\n if (\n compatibility\n .spectralResponseProfileId !==\n reduction.responseProfileId ||\n compatibility.colorSamplingProfileId !==\n reduction.colorSamplingProfileId ||\n compatibility.channelId !==\n reduction.channelId ||\n compatibility.responseScope !==\n reduction.responseScope\n ) {\n throw new InvalidScientificInputError(\n \"compatibility identities must exactly match the reduction.\"\n );\n }\n\n if (\n !operatingRange\n .operatingRangeCompatibilityAssessed ||\n !operatingRange\n .instantaneousResponseRangeCompatible ||\n !operatingRange\n .responseRateConversionAuthorized ||\n operatingRange.status === \"blocked\" ||\n operatingRange.blockers.length !== 0 ||\n operatingRange.requiredSignalPath !==\n \"radiant-power-to-current\" ||\n operatingRange\n .responseApplicationPerformed !==\n false ||\n operatingRange\n .currentConversionPerformed !== false ||\n operatingRange\n .temporalIntegrationAuthorized !== false ||\n !operatingRange\n .spectralNodeRangeCompatibilityAssessed ||\n operatingRange\n .spectralInputModel.kind !==\n \"per-spectral-bin\" ||\n operatingRange\n .spatialLinearityModel.kind !==\n \"linear-superposition-over-geometric-aperture\"\n ) {\n throw new InvalidScientificInputError(\n \"operatingRange must authorize a clean per-bin radiant-power-to-current path.\"\n );\n }\n\n if (\n operatingRange\n .spectralResponseProfileId !==\n reduction.responseProfileId ||\n operatingRange\n .colorSamplingProfileId !==\n reduction.colorSamplingProfileId ||\n operatingRange.channelId !==\n reduction.channelId ||\n operatingRange\n .responseApplicationProfileId !==\n compatibility.applicationProfileId\n ) {\n throw new InvalidScientificInputError(\n \"operatingRange identities must exactly match the reduction and compatibility assessment.\"\n );\n }\n}\n\nfunction validateReductionNodes(\n reduction:\n SensorSpatioSpectralIrradianceReduction\n): readonly SensorSpatioSpectralWavelengthReduction[] {\n if (\n !Array.isArray(\n reduction.perWavelength\n ) ||\n !Number.isSafeInteger(\n reduction.spectralNodeCount\n ) ||\n reduction.spectralNodeCount <= 0 ||\n reduction.perWavelength.length !==\n reduction.spectralNodeCount\n ) {\n throw new InvalidScientificInputError(\n \"reduction.perWavelength must contain exactly spectralNodeCount entries.\"\n );\n }\n\n let priorWavelength =\n Number.NEGATIVE_INFINITY;\n let normalizedWeightSum = 0;\n const totalPower:\n CompensatedSum = {\n sum: 0,\n correction: 0\n };\n\n reduction.perWavelength.forEach(\n (node, arrayIndex) => {\n const sampleIndex =\n requireSafeNonNegativeInteger(\n node.spectralSampleIndex,\n \"reduction.perWavelength[\" +\n arrayIndex +\n \"].spectralSampleIndex\"\n );\n if (sampleIndex !== arrayIndex) {\n throw new InvalidScientificInputError(\n \"reduction spectralSampleIndex values must form the exact contiguous range 0..spectralNodeCount-1.\"\n );\n }\n\n const wavelength =\n requirePositiveFiniteInput(\n node.wavelengthNanometers,\n \"reduction.perWavelength[\" +\n arrayIndex +\n \"].wavelengthNanometers\"\n );\n if (\n wavelength <= priorWavelength\n ) {\n throw new InvalidScientificInputError(\n \"reduction wavelength nodes must be strictly increasing.\"\n );\n }\n priorWavelength = wavelength;\n\n const measure =\n requirePositiveFiniteInput(\n node.wavelengthMeasureNanometers,\n \"reduction.perWavelength[\" +\n arrayIndex +\n \"].wavelengthMeasureNanometers\"\n );\n const normalizedWeight =\n requirePositiveFiniteInput(\n node.normalizedWavelengthWeight,\n \"reduction.perWavelength[\" +\n arrayIndex +\n \"].normalizedWavelengthWeight\"\n );\n const fluxDensity =\n requireNonNegativeFiniteInput(\n node\n .geometricApertureIncidentSpectralFluxWattsPerNanometer,\n \"reduction.perWavelength[\" +\n arrayIndex +\n \"].geometricApertureIncidentSpectralFluxWattsPerNanometer\"\n );\n const power =\n requireNonNegativeFiniteInput(\n node\n .wavelengthIntegratedGeometricApertureIncidentFluxContributionWatts,\n \"reduction.perWavelength[\" +\n arrayIndex +\n \"].wavelengthIntegratedGeometricApertureIncidentFluxContributionWatts\"\n );\n const expected =\n fluxDensity * measure;\n if (\n !Number.isFinite(expected) ||\n !approximatelyEqual(\n power,\n expected\n )\n ) {\n throw new InvalidScientificInputError(\n \"reduction per-wavelength radiant-power contribution must equal spectral flux density × d-lambda.\"\n );\n }\n\n normalizedWeightSum +=\n normalizedWeight;\n addCompensated(\n totalPower,\n power\n );\n }\n );\n\n if (\n !Number.isFinite(\n normalizedWeightSum\n ) ||\n !approximatelyEqual(\n normalizedWeightSum,\n 1\n )\n ) {\n throw new InvalidScientificInputError(\n \"reduction normalized wavelength weights must sum to 1.\"\n );\n }\n\n const reductionPower =\n requireNonNegativeFiniteInput(\n reduction\n .wavelengthIntegratedGeometricApertureIncidentFluxWatts,\n \"reduction.wavelengthIntegratedGeometricApertureIncidentFluxWatts\"\n );\n if (\n !approximatelyEqual(\n totalPower.sum,\n reductionPower\n )\n ) {\n throw new InvalidScientificInputError(\n \"reduction total geometric-aperture radiant power must match the per-wavelength sum.\"\n );\n }\n\n return reduction.perWavelength;\n}\n\nfunction validateOperatingRangeNodeBinding(\n reduction:\n SensorSpatioSpectralIrradianceReduction,\n nodes:\n readonly SensorSpatioSpectralWavelengthReduction[],\n operatingRange:\n SensorResponseOperatingRangeAssessment\n): void {\n const evaluated =\n operatingRange\n .evaluatedSpectralNodeInputs;\n\n if (\n evaluated === undefined ||\n evaluated.length !== nodes.length\n ) {\n throw new InvalidScientificInputError(\n \"operatingRange must carry one evaluated spectral-node input per reduction wavelength node.\"\n );\n }\n\n if (\n operatingRange\n .evaluatedWavelengthRangeNanometers\n .minimum !==\n reduction.wavelengthRangeNanometers\n .minimum ||\n operatingRange\n .evaluatedWavelengthRangeNanometers\n .maximum !==\n reduction.wavelengthRangeNanometers\n .maximum\n ) {\n throw new InvalidScientificInputError(\n \"operatingRange wavelength range must exactly match the reduction.\"\n );\n }\n\n evaluated.forEach(\n (entry, index) => {\n const node = nodes[index]!;\n if (\n entry.spectralSampleIndex !==\n node.spectralSampleIndex ||\n entry.wavelengthNanometers !==\n node.wavelengthNanometers ||\n entry.wavelengthMeasureNanometers !==\n node.wavelengthMeasureNanometers\n ) {\n throw new InvalidScientificInputError(\n \"operatingRange spectral-node identities must exactly match the reduction.\"\n );\n }\n\n const expected =\n operatingRange.inputRange.kind ===\n \"wavelength-integrated-geometric-aperture-radiant-power\"\n ? node\n .wavelengthIntegratedGeometricApertureIncidentFluxContributionWatts\n : node\n .wavelengthIntegratedSpatialAverageContributionWattsPerSquareMeter;\n\n if (\n entry.kind !==\n operatingRange.inputRange.kind ||\n entry.unit !==\n operatingRange.inputRange.unit ||\n !approximatelyEqual(\n entry.value,\n expected\n )\n ) {\n throw new InvalidScientificInputError(\n \"operatingRange spectral-node values must match the reduction values in the calibrated input domain.\"\n );\n }\n }\n );\n}\n\nfunction validateResponseBinding(\n resolved:\n ResolvedSensorSpectralResponse,\n reduction:\n SensorSpatioSpectralIrradianceReduction\n): void {\n if (\n resolved.profileId !==\n reduction.responseProfileId ||\n resolved.colorSamplingProfileId !==\n reduction.colorSamplingProfileId ||\n resolved.channelId !==\n reduction.channelId ||\n resolved.sourceResponseKind !==\n reduction.sourceResponseKind ||\n resolved.responseScope !==\n reduction.responseScope ||\n resolved.scientificStatus !==\n reduction.responseScientificStatus ||\n canonicalJson(\n resolved.uncertainty\n ) !==\n canonicalJson(\n reduction.responseUncertainty\n ) ||\n canonicalJson(\n resolved.componentEvidence\n ) !==\n canonicalJson({\n profile:\n reduction.componentEvidence\n .spectral.profile,\n channel:\n reduction.componentEvidence\n .spectral.channel,\n curves:\n reduction.componentEvidence\n .spectral.curves\n })\n ) {\n throw new InvalidScientificInputError(\n \"Resolved A/W response calibration metadata/evidence must exactly match the reduction.\"\n );\n }\n}\n\nfunction validateExactResponseDataBinding(\n responseProfile:\n SensorSpectralResponseProfile,\n reduction:\n SensorSpatioSpectralIrradianceReduction\n): void {\n const response =\n responseProfile.channels.find(\n (entry) =>\n entry.channelId ===\n reduction.channelId\n );\n if (reduction.responseChannelBinding !== undefined) {\n requireCurrentSensorSpectralResponseChannelBinding(\n reduction.responseChannelBinding\n );\n }\n if (\n response === undefined ||\n reduction.responseChannelBinding ===\n undefined ||\n canonicalJson(\n createSensorSpectralResponseChannelBinding(\n response\n )\n ) !==\n canonicalJson(\n reduction.responseChannelBinding\n )\n ) {\n throw new InvalidScientificInputError(\n \"Supplied spectral response channel data must exactly match the response-channel binding carried by the reduction.\"\n );\n }\n}\n\nfunction validateElectricalBinding(\n profile:\n SensorResponsivityElectricalApplicabilityProfile,\n input:\n CalculateSensorResponsivityPhotocurrentInput,\n operatingElectricalConditions:\n SensorResponsivityElectricalConditions\n): {\n compatibility:\n \"exact-match\" |\n \"assumed-compatible\";\n assumptionEvidence:\n readonly EvidenceProvenance[];\n} {\n if (\n profile.responseApplicationProfileId !==\n input.compatibility\n .applicationProfileId ||\n profile.spectralResponseProfileId !==\n input.reduction\n .responseProfileId ||\n profile.colorSamplingProfileId !==\n input.reduction\n .colorSamplingProfileId ||\n profile.channelId !==\n input.reduction.channelId\n ) {\n throw new InvalidScientificInputError(\n \"Electrical applicability profile identities must exactly match the response pipeline.\"\n );\n }\n\n if (\n profile.conditionPolicy.kind ===\n \"exact-match-required\"\n ) {\n if (\n !electricalConditionsMatch(\n profile.referenceConditions,\n operatingElectricalConditions\n )\n ) {\n throw new InvalidScientificInputError(\n \"Operating electrical conditions must exactly match the A/W calibration reference conditions.\"\n );\n }\n return {\n compatibility: \"exact-match\",\n assumptionEvidence: []\n };\n }\n\n return {\n compatibility:\n \"assumed-compatible\",\n assumptionEvidence:\n profile.conditionPolicy.evidence\n };\n}\n\n/**\n * Sums responsivity (A/W) × radiant power over wavelength bins to get the steady current magnitude,\n * under explicit electrical conditions.\n *\n * This is not EQE, an electron rate, a transimpedance voltage or RAW. Fast-changing current needs a\n * separate time-dependent detector model.\n * @param input - The input; see `CalculateSensorResponsivityPhotocurrentInput` for its fields, units and coordinates.\n * @returns The result. Success does not imply calibration.\n *\n * @see docs/API_REFERENCE.md for the package export and its full type definitions.\n */\nexport function calculateSensorResponsivityPhotocurrent(\n input:\n CalculateSensorResponsivityPhotocurrentInput\n): CalculationResult<SensorResponsivityPhotocurrent> {\n requireInputKeys(input, \"calculateSensorResponsivityPhotocurrent\", [\"reduction\", \"compatibility\", \"operatingRange\", \"colorSamplingProfile\", \"spectralResponseProfile\", \"electricalApplicabilityProfile\", \"operatingElectricalConditions\"]);\n validateAuthorizationChain(\n input.reduction,\n input.compatibility,\n input.operatingRange\n );\n\n if (\n input.reduction\n .sourceResponseKind !==\n \"effective-spectral-responsivity\"\n ) {\n throw new InvalidScientificInputError(\n \"A/W photocurrent conversion requires effective spectral responsivity, not EQE.\"\n );\n }\n\n const colorProfile =\n parseSensorColorSamplingProfile(\n input.colorSamplingProfile\n );\n const responseProfile =\n parseSensorSpectralResponseProfile(\n input.spectralResponseProfile\n );\n const electricalProfile =\n parseSensorResponsivityElectricalApplicabilityProfile(\n input.electricalApplicabilityProfile\n );\n\n if (\n colorProfile.profileId !==\n input.reduction\n .colorSamplingProfileId ||\n responseProfile.profileId !==\n input.reduction\n .responseProfileId ||\n responseProfile\n .colorSamplingProfileId !==\n colorProfile.profileId\n ) {\n throw new InvalidScientificInputError(\n \"Supplied color/spectral response profiles must exactly match the reduction identities.\"\n );\n }\n\n validateExactResponseDataBinding(\n responseProfile,\n input.reduction\n );\n\n const operatingElectricalConditions =\n parseElectricalConditions(\n input.operatingElectricalConditions,\n \"operatingElectricalConditions\"\n );\n const electrical =\n validateElectricalBinding(\n electricalProfile,\n input,\n operatingElectricalConditions\n );\n const nodes =\n validateReductionNodes(\n input.reduction\n );\n validateOperatingRangeNodeBinding(\n input.reduction,\n nodes,\n input.operatingRange\n );\n\n const currentSum:\n CompensatedSum = {\n sum: 0,\n correction: 0\n };\n const perWavelength:\n SensorResponsivityWavelengthCurrentContribution[] =\n [];\n let responseBindingValidated =\n false;\n\n for (const node of nodes) {\n const resolved =\n resolveParsedSensorSpectralResponseAtWavelength({\n colorSamplingProfile:\n colorProfile,\n spectralResponseProfile:\n responseProfile,\n channelId:\n input.reduction.channelId,\n wavelengthNanometers:\n node.wavelengthNanometers,\n wavelengthBasis:\n input.reduction\n .wavelengthBasis\n });\n\n if (!responseBindingValidated) {\n validateResponseBinding(\n resolved.value,\n input.reduction\n );\n responseBindingValidated =\n true;\n }\n\n const responsivity =\n resolved.value.response as Extract<\n typeof resolved.value.response,\n {\n kind:\n \"effective-spectral-responsivity\";\n }\n >;\n\n const radiantPowerContributionWatts =\n node\n .geometricApertureIncidentSpectralFluxWattsPerNanometer *\n node.wavelengthMeasureNanometers;\n const photocurrentMagnitudeContributionAmperes =\n radiantPowerContributionWatts *\n responsivity.amperesPerWatt;\n\n if (\n !Number.isFinite(\n radiantPowerContributionWatts\n ) ||\n !Number.isFinite(\n photocurrentMagnitudeContributionAmperes\n ) ||\n photocurrentMagnitudeContributionAmperes <\n 0\n ) {\n throw new InvalidScientificInputError(\n \"A/W wavelength-node photocurrent calculation must remain finite and nonnegative.\"\n );\n }\n\n addCompensated(\n currentSum,\n photocurrentMagnitudeContributionAmperes\n );\n\n perWavelength.push({\n spectralSampleIndex:\n node.spectralSampleIndex,\n wavelengthNanometers:\n node.wavelengthNanometers,\n wavelengthMeasureNanometers:\n node.wavelengthMeasureNanometers,\n geometricApertureIncidentSpectralFluxWattsPerNanometer:\n node\n .geometricApertureIncidentSpectralFluxWattsPerNanometer,\n radiantPowerContributionWatts,\n spectralResponsivityAmperesPerWatt:\n responsivity.amperesPerWatt,\n responseInterpolationUsed:\n resolved.value\n .interpolationUsed,\n photocurrentMagnitudeContributionAmperes\n });\n }\n\n if (\n !Number.isFinite(\n currentSum.sum\n ) ||\n currentSum.sum < 0\n ) {\n throw new InvalidScientificInputError(\n \"Total A/W photocurrent magnitude must remain finite and nonnegative.\"\n );\n }\n\n return approximationResult(\n {\n colorSamplingProfileId:\n input.reduction\n .colorSamplingProfileId,\n responseProfileId:\n input.reduction\n .responseProfileId,\n responseApplicationProfileId:\n input.compatibility\n .applicationProfileId,\n operatingRangeProfileId:\n input.operatingRange\n .operatingRangeProfileId,\n electricalApplicabilityProfileId:\n electricalProfile.profileId,\n site: {\n ...input.reduction.site\n },\n channelId:\n input.reduction.channelId,\n sourceResponseKind:\n \"effective-spectral-responsivity\",\n responseScope:\n input.reduction.responseScope,\n responseReferencePlane:\n input.compatibility\n .requiredSourcePlane,\n wavelengthBasis:\n input.reduction\n .wavelengthBasis,\n wavelengthRangeNanometers: {\n ...input.reduction\n .wavelengthRangeNanometers\n },\n electricalReferenceConditions:\n electricalProfile\n .referenceConditions,\n operatingElectricalConditions,\n electricalConditionPolicy:\n electricalProfile\n .conditionPolicy,\n electricalCompatibility:\n electrical.compatibility,\n spectralNodeCount:\n nodes.length,\n perWavelength,\n photocurrentMagnitudeAmperes:\n currentSum.sum,\n currentSignConvention:\n \"magnitude-only-no-circuit-polarity\",\n summationMethod:\n \"kahan-compensated\",\n responseApplicationPerformed:\n true,\n spectralResponsivityApplied:\n true,\n quantumEfficiencyApplied:\n false,\n photonRateCalculated: false,\n electronRateCalculated: false,\n currentCalculated: true,\n chargeCalculated: false,\n temporalResponseModel:\n \"quasi-static-steady-state-only\",\n detectorBandwidthModeled: false,\n transimpedanceGainApplied:\n false,\n voltageCalculated: false,\n temporalIntegrationApplied:\n false,\n exposureDurationApplied: false,\n saturationAssessed: false,\n readoutElectronicsLinearityAssessed:\n false,\n shotNoiseApplied: false,\n readNoiseApplied: false,\n adcQuantizationApplied:\n false,\n rawCodeValueProduced: false,\n responseUncertaintyPropagated:\n false,\n electricalApplicabilityUncertaintyPropagated:\n false,\n quadratureConvergenceErrorEstimated:\n false,\n componentEvidence: {\n electricalApplicability:\n electricalProfile.evidence,\n electricalConditionAssumption:\n electrical\n .assumptionEvidence\n }\n },\n \"sensor-spectral-responsivity-photocurrent\",\n \"1.0.0\",\n [\n \"Spectral responsivity in A/W is applied independently at every wavelength quadrature node as detector-terminal photocurrent magnitude per incident radiant power.\",\n \"Current sign/polarity is deliberately not modeled; the result is a nonnegative photocurrent magnitude and does not imply a circuit current direction.\",\n \"The A/W calibration is bound to explicit detector electrical conditions. Exact-match mode requires identical bias and readout-load semantics; approximation mode requires evidence and a stated limitation.\",\n \"Virtual-ground current readout and finite input impedance are modeled as calibration-condition identities only; this function does not simulate amplifier circuits or prove impedance adequacy.\",\n \"NIST photodiode guidance shows detector/electronics/loading can affect linear operation, so transimpedance/current-readout conditions are not treated as scientifically inert.\",\n \"Structural compatibility, geometric-aperture linear superposition and per-spectral-bin operating-range applicability must already authorize the radiant-power→current path.\",\n \"Response metadata/evidence and operating-range spectral-node values are rebound to the exact reduction so matching IDs alone or stale authorization cannot enable conversion.\",\n \"The calculation does not use photon energy, QE, photon rate or electron rate. A/W remains a distinct current-domain response representation.\",\n \"No transimpedance gain or voltage conversion is performed; current-to-voltage converter gain/offset/linearity remain downstream electronics contracts.\",\n \"The A/W response is used only as a quasi-static steady-state power→current mapping. Detector impulse response, bandwidth, modulation-frequency response and transient settling are not modeled.\",\n \"Outputs are instantaneous current only. Exposure-time integration to charge, saturation, noise, ADC/RAW conversion and reconstruction remain downstream.\",\n \"Response/electrical uncertainties and quadrature convergence error are not propagated into a combined current uncertainty by this version.\"\n ]\n );\n}\n"]}
|