@photivra/engine 0.5.1 → 0.6.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 +32 -0
- package/CITATION.cff +1 -1
- package/README.md +37 -3
- package/dist/index.d.ts +15 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -2
- package/dist/index.js.map +1 -1
- package/dist/motion/camera-rotation.d.ts +60 -0
- package/dist/motion/camera-rotation.d.ts.map +1 -1
- package/dist/motion/camera-rotation.js +95 -0
- package/dist/motion/camera-rotation.js.map +1 -1
- package/dist/motion/capture-rotation-inverse-mapping.d.ts +100 -0
- package/dist/motion/capture-rotation-inverse-mapping.d.ts.map +1 -0
- package/dist/motion/capture-rotation-inverse-mapping.js +171 -0
- package/dist/motion/capture-rotation-inverse-mapping.js.map +1 -0
- package/dist/motion/capture-rotation-temporal-quadrature.d.ts +89 -0
- package/dist/motion/capture-rotation-temporal-quadrature.d.ts.map +1 -0
- package/dist/motion/capture-rotation-temporal-quadrature.js +116 -0
- package/dist/motion/capture-rotation-temporal-quadrature.js.map +1 -0
- package/dist/motion/capture-rotation-trajectory.d.ts +98 -0
- package/dist/motion/capture-rotation-trajectory.d.ts.map +1 -0
- package/dist/motion/capture-rotation-trajectory.js +153 -0
- package/dist/motion/capture-rotation-trajectory.js.map +1 -0
- package/dist/optics/lateral-chromatic-aberration.d.ts.map +1 -1
- package/dist/optics/lateral-chromatic-aberration.js +12 -4
- package/dist/optics/lateral-chromatic-aberration.js.map +1 -1
- package/dist/optics/radial-distortion.d.ts +4 -2
- package/dist/optics/radial-distortion.d.ts.map +1 -1
- package/dist/optics/radial-distortion.js +83 -23
- package/dist/optics/radial-distortion.js.map +1 -1
- package/dist/output/capture-geometry.d.ts.map +1 -1
- package/dist/output/capture-geometry.js +24 -11
- package/dist/output/capture-geometry.js.map +1 -1
- package/dist/sensor/capture-color-sampling-binding.d.ts +211 -0
- package/dist/sensor/capture-color-sampling-binding.d.ts.map +1 -0
- package/dist/sensor/capture-color-sampling-binding.js +423 -0
- package/dist/sensor/capture-color-sampling-binding.js.map +1 -0
- package/dist/sensor/capture-mode.d.ts +157 -0
- package/dist/sensor/capture-mode.d.ts.map +1 -0
- package/dist/sensor/capture-mode.js +434 -0
- package/dist/sensor/capture-mode.js.map +1 -0
- package/dist/sensor/color-sampling.d.ts +133 -0
- package/dist/sensor/color-sampling.d.ts.map +1 -0
- package/dist/sensor/color-sampling.js +226 -0
- package/dist/sensor/color-sampling.js.map +1 -0
- package/dist/sensor/exposure-window.d.ts +103 -0
- package/dist/sensor/exposure-window.d.ts.map +1 -0
- package/dist/sensor/exposure-window.js +291 -0
- package/dist/sensor/exposure-window.js.map +1 -0
- package/dist/sensor/optical-stack.d.ts +132 -0
- package/dist/sensor/optical-stack.d.ts.map +1 -0
- package/dist/sensor/optical-stack.js +286 -0
- package/dist/sensor/optical-stack.js.map +1 -0
- package/dist/sensor/readout-exposure-linkage.d.ts +111 -0
- package/dist/sensor/readout-exposure-linkage.d.ts.map +1 -0
- package/dist/sensor/readout-exposure-linkage.js +210 -0
- package/dist/sensor/readout-exposure-linkage.js.map +1 -0
- package/dist/sensor/readout-timing.d.ts +124 -0
- package/dist/sensor/readout-timing.d.ts.map +1 -0
- package/dist/sensor/readout-timing.js +230 -0
- package/dist/sensor/readout-timing.js.map +1 -0
- package/dist/sensor/sampling-aperture.d.ts +154 -0
- package/dist/sensor/sampling-aperture.d.ts.map +1 -0
- package/dist/sensor/sampling-aperture.js +374 -0
- package/dist/sensor/sampling-aperture.js.map +1 -0
- package/dist/sensor/spatial-sample-reduction.d.ts +128 -0
- package/dist/sensor/spatial-sample-reduction.d.ts.map +1 -0
- package/dist/sensor/spatial-sample-reduction.js +299 -0
- package/dist/sensor/spatial-sample-reduction.js.map +1 -0
- package/dist/sensor/spatial-sampling-quadrature.d.ts +155 -0
- package/dist/sensor/spatial-sampling-quadrature.d.ts.map +1 -0
- package/dist/sensor/spatial-sampling-quadrature.js +197 -0
- package/dist/sensor/spatial-sampling-quadrature.js.map +1 -0
- package/docs/ARCHITECTURE.md +17 -0
- package/docs/AUTOMATION_COORDINATION.md +188 -0
- package/docs/IMAGE_FORMATION.md +26 -0
- package/docs/MOTION_AND_SIGNAL.md +142 -0
- package/docs/USAGE.md +1273 -3
- package/package.json +5 -3
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { type CalculationResult } from "../core/calculation-result.js";
|
|
2
|
+
import { type EvidenceBackedFact } from "../core/evidence-provenance.js";
|
|
3
|
+
import type { RasterPoint, RasterRect } from "../output/capture-geometry.js";
|
|
4
|
+
import type { NativeImageRaster } from "./sensor-geometry.js";
|
|
5
|
+
import type { SensorReadoutArchitecture } from "./architecture.js";
|
|
6
|
+
/**
|
|
7
|
+
* Readout architecture selected for one capture.
|
|
8
|
+
*
|
|
9
|
+
* This reuses the architecture vocabulary but is not a hardware-capability
|
|
10
|
+
* assertion. SensorArchitectureProfile.readoutCapabilities remains descriptive
|
|
11
|
+
* metadata and is not consulted automatically.
|
|
12
|
+
*/
|
|
13
|
+
export type SensorReadoutMode = SensorReadoutArchitecture;
|
|
14
|
+
export type NativeSensorReadoutScanDirection = "top-to-bottom" | "bottom-to-top" | "left-to-right" | "right-to-left";
|
|
15
|
+
export type CaptureShutterMechanism = "mechanical" | "electronic-first-curtain" | "electronic";
|
|
16
|
+
/**
|
|
17
|
+
* Evidence-backed timing value with an explicit seconds unit.
|
|
18
|
+
*/
|
|
19
|
+
export interface SourcedSensorTimingSeconds extends EvidenceBackedFact<number> {
|
|
20
|
+
unit: "s";
|
|
21
|
+
}
|
|
22
|
+
export type SourcedSensorReadoutFact<T> = EvidenceBackedFact<T>;
|
|
23
|
+
export interface GlobalSensorReadoutTimingDeclaration {
|
|
24
|
+
readoutMode: "global";
|
|
25
|
+
/**
|
|
26
|
+
* Capture-specific sensor data-readout duration.
|
|
27
|
+
*
|
|
28
|
+
* This is deliberately not interpreted as spatial exposure/readout skew.
|
|
29
|
+
*/
|
|
30
|
+
captureReadoutDurationSeconds: SourcedSensorTimingSeconds;
|
|
31
|
+
scanDirectionNative?: never;
|
|
32
|
+
spatialSamplingSkewSeconds?: never;
|
|
33
|
+
}
|
|
34
|
+
export interface RollingSensorReadoutTimingDeclaration {
|
|
35
|
+
readoutMode: "rolling";
|
|
36
|
+
/**
|
|
37
|
+
* Capture-specific sensor data-readout duration.
|
|
38
|
+
*
|
|
39
|
+
* This fact is retained independently from spatial sampling skew because
|
|
40
|
+
* published/declared readout duration and the spatial timing span need not be
|
|
41
|
+
* treated as the same quantity.
|
|
42
|
+
*/
|
|
43
|
+
captureReadoutDurationSeconds: SourcedSensorTimingSeconds;
|
|
44
|
+
/**
|
|
45
|
+
* Native-sensor scan direction for the selected capture mode.
|
|
46
|
+
*/
|
|
47
|
+
scanDirectionNative: SourcedSensorReadoutFact<NativeSensorReadoutScanDirection>;
|
|
48
|
+
/**
|
|
49
|
+
* Time difference between the first and last spatial scan positions in the
|
|
50
|
+
* uniform-linear timing approximation.
|
|
51
|
+
*/
|
|
52
|
+
spatialSamplingSkewSeconds: SourcedSensorTimingSeconds;
|
|
53
|
+
}
|
|
54
|
+
export type SensorReadoutTimingDeclaration = GlobalSensorReadoutTimingDeclaration | RollingSensorReadoutTimingDeclaration;
|
|
55
|
+
export interface CalculateSensorReadoutTimingInput {
|
|
56
|
+
nativeRaster: NativeImageRaster;
|
|
57
|
+
/**
|
|
58
|
+
* Active capture rectangle in invariant native raster coordinates.
|
|
59
|
+
*
|
|
60
|
+
* Defaults to the complete native raster. Timing is never inferred by
|
|
61
|
+
* scaling a full-frame value to this rectangle.
|
|
62
|
+
*/
|
|
63
|
+
activeCaptureRect?: RasterRect;
|
|
64
|
+
/**
|
|
65
|
+
* Selected shutter mechanism for the capture.
|
|
66
|
+
*
|
|
67
|
+
* It is reported independently and does not modify the sensor timing
|
|
68
|
+
* schedule in this foundation.
|
|
69
|
+
*/
|
|
70
|
+
shutterMechanism: CaptureShutterMechanism;
|
|
71
|
+
readout: SensorReadoutTimingDeclaration;
|
|
72
|
+
/**
|
|
73
|
+
* Optional continuous native raster edge-coordinate points for timing
|
|
74
|
+
* diagnostics. Pixel centers may be represented with +0.5 offsets.
|
|
75
|
+
*/
|
|
76
|
+
samplePointsNative?: readonly RasterPoint[];
|
|
77
|
+
}
|
|
78
|
+
export interface SensorReadoutTimingSample {
|
|
79
|
+
pointNative: RasterPoint;
|
|
80
|
+
normalizedScanPosition: number | null;
|
|
81
|
+
/**
|
|
82
|
+
* Relative native-sensor readout phase in seconds.
|
|
83
|
+
*
|
|
84
|
+
* Zero is the first spatial scan position. This is not automatically an
|
|
85
|
+
* exposure-start time or shutter-curtain time.
|
|
86
|
+
*/
|
|
87
|
+
readoutPhaseOffsetSeconds: number;
|
|
88
|
+
}
|
|
89
|
+
export interface SensorReadoutTiming {
|
|
90
|
+
readoutMode: SensorReadoutMode;
|
|
91
|
+
shutterMechanism: CaptureShutterMechanism;
|
|
92
|
+
nativeRaster: NativeImageRaster;
|
|
93
|
+
activeCaptureRect: RasterRect;
|
|
94
|
+
captureReadoutDurationSeconds: SourcedSensorTimingSeconds;
|
|
95
|
+
maximumSpatialSamplingSkewSeconds: number;
|
|
96
|
+
scan: {
|
|
97
|
+
pattern: "uniform-linear-single-axis";
|
|
98
|
+
directionNative: SourcedSensorReadoutFact<NativeSensorReadoutScanDirection>;
|
|
99
|
+
unitVectorNative: {
|
|
100
|
+
x: number;
|
|
101
|
+
y: number;
|
|
102
|
+
};
|
|
103
|
+
spatialSamplingSkewSeconds: SourcedSensorTimingSeconds;
|
|
104
|
+
} | null;
|
|
105
|
+
samples: readonly SensorReadoutTimingSample[];
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Resolves a capture-specific native sensor readout scan schedule.
|
|
109
|
+
*
|
|
110
|
+
* Rolling readout uses a uniform-linear single-axis approximation across the
|
|
111
|
+
* declared active capture. The caller supplies the spatial timing span
|
|
112
|
+
* explicitly; it is never inferred from total data-readout duration, active
|
|
113
|
+
* crop dimensions, native raster density, output resolution, sensor
|
|
114
|
+
* architecture metadata, or shutter mechanism.
|
|
115
|
+
*
|
|
116
|
+
* Global readout has no spatial phase skew in this model even when a non-zero
|
|
117
|
+
* data-readout duration is declared.
|
|
118
|
+
*
|
|
119
|
+
* This foundation does not define local exposure start/end times, mechanical
|
|
120
|
+
* curtain travel, EFCS curtain behavior, rolling-shutter image distortion,
|
|
121
|
+
* flash/flicker interactions, or motion integration.
|
|
122
|
+
*/
|
|
123
|
+
export declare function calculateSensorReadoutTiming(input: CalculateSensorReadoutTimingInput): CalculationResult<SensorReadoutTiming>;
|
|
124
|
+
//# sourceMappingURL=readout-timing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readout-timing.d.ts","sourceRoot":"","sources":["../../src/sensor/readout-timing.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAC5F,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAEnE;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,yBAAyB,CAAC;AAE1D,MAAM,MAAM,gCAAgC,GACxC,eAAe,GACf,eAAe,GACf,eAAe,GACf,eAAe,CAAC;AAEpB,MAAM,MAAM,uBAAuB,GAC/B,YAAY,GACZ,0BAA0B,GAC1B,YAAY,CAAC;AAEjB;;GAEG;AACH,MAAM,WAAW,0BACf,SAAQ,kBAAkB,CAAC,MAAM,CAAC;IAClC,IAAI,EAAE,GAAG,CAAC;CACX;AAED,MAAM,MAAM,wBAAwB,CAAC,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,CAAC;AAEhE,MAAM,WAAW,oCAAoC;IACnD,WAAW,EAAE,QAAQ,CAAC;IACtB;;;;OAIG;IACH,6BAA6B,EAAE,0BAA0B,CAAC;IAC1D,mBAAmB,CAAC,EAAE,KAAK,CAAC;IAC5B,0BAA0B,CAAC,EAAE,KAAK,CAAC;CACpC;AAED,MAAM,WAAW,qCAAqC;IACpD,WAAW,EAAE,SAAS,CAAC;IACvB;;;;;;OAMG;IACH,6BAA6B,EAAE,0BAA0B,CAAC;IAC1D;;OAEG;IACH,mBAAmB,EAAE,wBAAwB,CAAC,gCAAgC,CAAC,CAAC;IAChF;;;OAGG;IACH,0BAA0B,EAAE,0BAA0B,CAAC;CACxD;AAED,MAAM,MAAM,8BAA8B,GACtC,oCAAoC,GACpC,qCAAqC,CAAC;AAE1C,MAAM,WAAW,iCAAiC;IAChD,YAAY,EAAE,iBAAiB,CAAC;IAChC;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAC/B;;;;;OAKG;IACH,gBAAgB,EAAE,uBAAuB,CAAC;IAC1C,OAAO,EAAE,8BAA8B,CAAC;IACxC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,WAAW,CAAC;IACzB,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC;;;;;OAKG;IACH,yBAAyB,EAAE,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,iBAAiB,CAAC;IAC/B,gBAAgB,EAAE,uBAAuB,CAAC;IAC1C,YAAY,EAAE,iBAAiB,CAAC;IAChC,iBAAiB,EAAE,UAAU,CAAC;IAC9B,6BAA6B,EAAE,0BAA0B,CAAC;IAC1D,iCAAiC,EAAE,MAAM,CAAC;IAC1C,IAAI,EACA;QACE,OAAO,EAAE,4BAA4B,CAAC;QACtC,eAAe,EAAE,wBAAwB,CAAC,gCAAgC,CAAC,CAAC;QAC5E,gBAAgB,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC3C,0BAA0B,EAAE,0BAA0B,CAAC;KACxD,GACD,IAAI,CAAC;IACT,OAAO,EAAE,SAAS,yBAAyB,EAAE,CAAC;CAC/C;AAkPD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,iCAAiC,GACvC,iBAAiB,CAAC,mBAAmB,CAAC,CAmFxC"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { approximationResult } from "../core/calculation-result.js";
|
|
3
|
+
import { parseEvidenceList } from "../core/evidence-provenance.js";
|
|
4
|
+
import { InvalidScientificInputError, requirePositiveInteger } from "../core/validation.js";
|
|
5
|
+
const READOUT_MODES = new Set(["rolling", "global"]);
|
|
6
|
+
const SCAN_DIRECTIONS = new Set([
|
|
7
|
+
"top-to-bottom",
|
|
8
|
+
"bottom-to-top",
|
|
9
|
+
"left-to-right",
|
|
10
|
+
"right-to-left"
|
|
11
|
+
]);
|
|
12
|
+
const SHUTTER_MECHANISMS = new Set([
|
|
13
|
+
"mechanical",
|
|
14
|
+
"electronic-first-curtain",
|
|
15
|
+
"electronic"
|
|
16
|
+
]);
|
|
17
|
+
function requireRecord(value, path) {
|
|
18
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
19
|
+
throw new InvalidScientificInputError(path + " must be an object.");
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
function requireNonNegativeInteger(name, value) {
|
|
24
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
25
|
+
throw new InvalidScientificInputError(name + " must be a non-negative safe integer.");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function requireNonNegativeFinite(name, value) {
|
|
29
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
30
|
+
throw new InvalidScientificInputError(name + " must be a finite number greater than or equal to zero.");
|
|
31
|
+
}
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
function requirePositiveFinite(name, value) {
|
|
35
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
36
|
+
throw new InvalidScientificInputError(name + " must be a finite number greater than zero.");
|
|
37
|
+
}
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
function parseSecondsFact(value, path, positive) {
|
|
41
|
+
const record = requireRecord(value, path);
|
|
42
|
+
if (record.unit !== "s") {
|
|
43
|
+
throw new InvalidScientificInputError(path + '.unit must be "s".');
|
|
44
|
+
}
|
|
45
|
+
const seconds = positive
|
|
46
|
+
? requirePositiveFinite(path + ".value", record.value)
|
|
47
|
+
: requireNonNegativeFinite(path + ".value", record.value);
|
|
48
|
+
return {
|
|
49
|
+
value: seconds,
|
|
50
|
+
unit: "s",
|
|
51
|
+
evidence: parseEvidenceList(record.evidence, path + ".evidence")
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function parseDirectionFact(value, path) {
|
|
55
|
+
const record = requireRecord(value, path);
|
|
56
|
+
if (typeof record.value !== "string" ||
|
|
57
|
+
!SCAN_DIRECTIONS.has(record.value)) {
|
|
58
|
+
throw new InvalidScientificInputError(path + ".value is invalid.");
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
value: record.value,
|
|
62
|
+
evidence: parseEvidenceList(record.evidence, path + ".evidence")
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function parseReadoutDeclaration(value) {
|
|
66
|
+
const record = requireRecord(value, "readout");
|
|
67
|
+
if (typeof record.readoutMode !== "string" ||
|
|
68
|
+
!READOUT_MODES.has(record.readoutMode)) {
|
|
69
|
+
throw new InvalidScientificInputError("readout.readoutMode is invalid.");
|
|
70
|
+
}
|
|
71
|
+
const captureReadoutDurationSeconds = parseSecondsFact(record.captureReadoutDurationSeconds, "readout.captureReadoutDurationSeconds", false);
|
|
72
|
+
if (record.readoutMode === "global") {
|
|
73
|
+
if (record.scanDirectionNative !== undefined) {
|
|
74
|
+
throw new InvalidScientificInputError("readout.scanDirectionNative must be omitted for global readout.");
|
|
75
|
+
}
|
|
76
|
+
if (record.spatialSamplingSkewSeconds !== undefined) {
|
|
77
|
+
throw new InvalidScientificInputError("readout.spatialSamplingSkewSeconds must be omitted for global readout.");
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
readoutMode: "global",
|
|
81
|
+
captureReadoutDurationSeconds
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
readoutMode: "rolling",
|
|
86
|
+
captureReadoutDurationSeconds,
|
|
87
|
+
scanDirectionNative: parseDirectionFact(record.scanDirectionNative, "readout.scanDirectionNative"),
|
|
88
|
+
spatialSamplingSkewSeconds: parseSecondsFact(record.spatialSamplingSkewSeconds, "readout.spatialSamplingSkewSeconds", true)
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function validateNativeRaster(raster) {
|
|
92
|
+
requirePositiveInteger("nativeRaster.pixelWidth", raster.pixelWidth);
|
|
93
|
+
requirePositiveInteger("nativeRaster.pixelHeight", raster.pixelHeight);
|
|
94
|
+
}
|
|
95
|
+
function fullRect(raster) {
|
|
96
|
+
return {
|
|
97
|
+
x: 0,
|
|
98
|
+
y: 0,
|
|
99
|
+
width: raster.pixelWidth,
|
|
100
|
+
height: raster.pixelHeight
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function validateActiveCaptureRect(rect, raster) {
|
|
104
|
+
requireNonNegativeInteger("activeCaptureRect.x", rect.x);
|
|
105
|
+
requireNonNegativeInteger("activeCaptureRect.y", rect.y);
|
|
106
|
+
requirePositiveInteger("activeCaptureRect.width", rect.width);
|
|
107
|
+
requirePositiveInteger("activeCaptureRect.height", rect.height);
|
|
108
|
+
if (rect.x + rect.width > raster.pixelWidth ||
|
|
109
|
+
rect.y + rect.height > raster.pixelHeight) {
|
|
110
|
+
throw new InvalidScientificInputError("activeCaptureRect must fit entirely within nativeRaster.");
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function validateShutterMechanism(value) {
|
|
114
|
+
if (typeof value !== "string" ||
|
|
115
|
+
!SHUTTER_MECHANISMS.has(value)) {
|
|
116
|
+
throw new InvalidScientificInputError("shutterMechanism is invalid.");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function validatePointWithinActiveCapture(point, rect, index) {
|
|
120
|
+
if (!Number.isFinite(point.x) || !Number.isFinite(point.y)) {
|
|
121
|
+
throw new InvalidScientificInputError("samplePointsNative[" + index + "] coordinates must be finite.");
|
|
122
|
+
}
|
|
123
|
+
if (point.x < rect.x ||
|
|
124
|
+
point.x > rect.x + rect.width ||
|
|
125
|
+
point.y < rect.y ||
|
|
126
|
+
point.y > rect.y + rect.height) {
|
|
127
|
+
throw new InvalidScientificInputError("samplePointsNative[" +
|
|
128
|
+
index +
|
|
129
|
+
"] must lie within activeCaptureRect edge-coordinate bounds.");
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function scanVector(direction) {
|
|
133
|
+
switch (direction) {
|
|
134
|
+
case "top-to-bottom":
|
|
135
|
+
return { x: 0, y: 1 };
|
|
136
|
+
case "bottom-to-top":
|
|
137
|
+
return { x: 0, y: -1 };
|
|
138
|
+
case "left-to-right":
|
|
139
|
+
return { x: 1, y: 0 };
|
|
140
|
+
case "right-to-left":
|
|
141
|
+
return { x: -1, y: 0 };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function normalizedScanPosition(point, rect, direction) {
|
|
145
|
+
switch (direction) {
|
|
146
|
+
case "top-to-bottom":
|
|
147
|
+
return (point.y - rect.y) / rect.height;
|
|
148
|
+
case "bottom-to-top":
|
|
149
|
+
return 1 - (point.y - rect.y) / rect.height;
|
|
150
|
+
case "left-to-right":
|
|
151
|
+
return (point.x - rect.x) / rect.width;
|
|
152
|
+
case "right-to-left":
|
|
153
|
+
return 1 - (point.x - rect.x) / rect.width;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Resolves a capture-specific native sensor readout scan schedule.
|
|
158
|
+
*
|
|
159
|
+
* Rolling readout uses a uniform-linear single-axis approximation across the
|
|
160
|
+
* declared active capture. The caller supplies the spatial timing span
|
|
161
|
+
* explicitly; it is never inferred from total data-readout duration, active
|
|
162
|
+
* crop dimensions, native raster density, output resolution, sensor
|
|
163
|
+
* architecture metadata, or shutter mechanism.
|
|
164
|
+
*
|
|
165
|
+
* Global readout has no spatial phase skew in this model even when a non-zero
|
|
166
|
+
* data-readout duration is declared.
|
|
167
|
+
*
|
|
168
|
+
* This foundation does not define local exposure start/end times, mechanical
|
|
169
|
+
* curtain travel, EFCS curtain behavior, rolling-shutter image distortion,
|
|
170
|
+
* flash/flicker interactions, or motion integration.
|
|
171
|
+
*/
|
|
172
|
+
export function calculateSensorReadoutTiming(input) {
|
|
173
|
+
validateNativeRaster(input.nativeRaster);
|
|
174
|
+
validateShutterMechanism(input.shutterMechanism);
|
|
175
|
+
const readout = parseReadoutDeclaration(input.readout);
|
|
176
|
+
const activeCaptureRect = input.activeCaptureRect ?? fullRect(input.nativeRaster);
|
|
177
|
+
validateActiveCaptureRect(activeCaptureRect, input.nativeRaster);
|
|
178
|
+
if (input.samplePointsNative !== undefined &&
|
|
179
|
+
!Array.isArray(input.samplePointsNative)) {
|
|
180
|
+
throw new InvalidScientificInputError("samplePointsNative must be an array when supplied.");
|
|
181
|
+
}
|
|
182
|
+
const scan = readout.readoutMode === "rolling"
|
|
183
|
+
? {
|
|
184
|
+
pattern: "uniform-linear-single-axis",
|
|
185
|
+
directionNative: readout.scanDirectionNative,
|
|
186
|
+
unitVectorNative: scanVector(readout.scanDirectionNative.value),
|
|
187
|
+
spatialSamplingSkewSeconds: readout.spatialSamplingSkewSeconds
|
|
188
|
+
}
|
|
189
|
+
: null;
|
|
190
|
+
const samples = (input.samplePointsNative ?? []).map((point, index) => {
|
|
191
|
+
validatePointWithinActiveCapture(point, activeCaptureRect, index);
|
|
192
|
+
if (scan === null) {
|
|
193
|
+
return {
|
|
194
|
+
pointNative: { x: point.x, y: point.y },
|
|
195
|
+
normalizedScanPosition: null,
|
|
196
|
+
readoutPhaseOffsetSeconds: 0
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
const normalized = normalizedScanPosition(point, activeCaptureRect, scan.directionNative.value);
|
|
200
|
+
return {
|
|
201
|
+
pointNative: { x: point.x, y: point.y },
|
|
202
|
+
normalizedScanPosition: normalized,
|
|
203
|
+
readoutPhaseOffsetSeconds: normalized * scan.spatialSamplingSkewSeconds.value
|
|
204
|
+
};
|
|
205
|
+
});
|
|
206
|
+
return approximationResult({
|
|
207
|
+
readoutMode: readout.readoutMode,
|
|
208
|
+
shutterMechanism: input.shutterMechanism,
|
|
209
|
+
nativeRaster: { ...input.nativeRaster },
|
|
210
|
+
activeCaptureRect: { ...activeCaptureRect },
|
|
211
|
+
captureReadoutDurationSeconds: readout.captureReadoutDurationSeconds,
|
|
212
|
+
maximumSpatialSamplingSkewSeconds: readout.readoutMode === "rolling"
|
|
213
|
+
? readout.spatialSamplingSkewSeconds.value
|
|
214
|
+
: 0,
|
|
215
|
+
scan,
|
|
216
|
+
samples
|
|
217
|
+
}, "native-sensor-readout-scan-timing", "1.0.0", [
|
|
218
|
+
"Native raster coordinates use top-left origin, +X right and +Y down and remain invariant under physical camera orientation.",
|
|
219
|
+
"Rolling timing uses a uniform-linear single-axis approximation over continuous effective native-raster coordinates.",
|
|
220
|
+
"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.",
|
|
221
|
+
"Capture data-readout duration and spatial sampling skew are independently declared facts; no equality or ordering relationship is inferred between them.",
|
|
222
|
+
"Global readout has zero spatial sampling skew in this model even when capture data-readout duration is non-zero.",
|
|
223
|
+
"Active-capture timing is caller-declared and is not inferred by scaling full-frame timing by crop dimensions.",
|
|
224
|
+
"Physical orientation and digital output crop/resolution are downstream of this invariant native timing schedule.",
|
|
225
|
+
"Shutter mechanism is reported independently and does not alter the sensor scan schedule in this foundation.",
|
|
226
|
+
"The model does not represent segmented, center-out, interleaved, multi-tap or other non-uniform readout patterns.",
|
|
227
|
+
"The model does not define exposure windows, shutter-curtain travel, rolling-shutter geometry distortion, flash/flicker interaction or camera/subject motion integration."
|
|
228
|
+
]);
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=readout-timing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readout-timing.js","sourceRoot":"","sources":["../../src/sensor/readout-timing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { type EvidenceProvenance } from "../core/evidence-provenance.js";
|
|
2
|
+
import { type NativeEffectiveRasterColorSamplingBindingProfile } from "./capture-color-sampling-binding.js";
|
|
3
|
+
import { type NativeColorSamplingSiteIndex, type SensorColorSamplingProfile } from "./color-sampling.js";
|
|
4
|
+
import type { NativeImageRaster, SensorImagingArea } from "./sensor-geometry.js";
|
|
5
|
+
export interface SensorSiteCenterLatticeRegistration {
|
|
6
|
+
kind: "regular-rectangular-site-center-lattice";
|
|
7
|
+
coordinateSystem: "native-sensor-physical";
|
|
8
|
+
/** Horizontal site-center pitch in micrometres. */
|
|
9
|
+
pitchXMicrometers: number;
|
|
10
|
+
/** Vertical site-center pitch in micrometres. */
|
|
11
|
+
pitchYMicrometers: number;
|
|
12
|
+
/**
|
|
13
|
+
* First site center relative to the imaging area's physical top-left edge.
|
|
14
|
+
*
|
|
15
|
+
* +X right, +Y down. Units: micrometres.
|
|
16
|
+
*/
|
|
17
|
+
firstSiteCenterFromImagingAreaTopLeftMicrometers: {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
};
|
|
21
|
+
evidence: readonly EvidenceProvenance[];
|
|
22
|
+
}
|
|
23
|
+
export type SensorGeometricSensitiveAperture = {
|
|
24
|
+
/**
|
|
25
|
+
* The physical/light-sensitive spatial aperture is known to matter but
|
|
26
|
+
* its geometry is not defensibly resolved.
|
|
27
|
+
*/
|
|
28
|
+
kind: "unresolved";
|
|
29
|
+
evidence: readonly EvidenceProvenance[];
|
|
30
|
+
} | {
|
|
31
|
+
/**
|
|
32
|
+
* First geometric sensitive-region approximation.
|
|
33
|
+
*
|
|
34
|
+
* This rectangle is constrained to remain inside one regular lattice
|
|
35
|
+
* cell, so neighboring geometric sensitive regions do not overlap in
|
|
36
|
+
* schema 0.1.0.
|
|
37
|
+
*/
|
|
38
|
+
kind: "uniform-axis-aligned-rectangle";
|
|
39
|
+
widthMicrometers: number;
|
|
40
|
+
heightMicrometers: number;
|
|
41
|
+
centerOffsetFromSiteCenterMicrometers: {
|
|
42
|
+
x: number;
|
|
43
|
+
y: number;
|
|
44
|
+
};
|
|
45
|
+
evidence: readonly EvidenceProvenance[];
|
|
46
|
+
};
|
|
47
|
+
export interface SensorSamplingApertureProfile {
|
|
48
|
+
schemaVersion: "0.1.0";
|
|
49
|
+
profileId: string;
|
|
50
|
+
colorSamplingProfileId: string;
|
|
51
|
+
colorSamplingBindingId: string;
|
|
52
|
+
evidence: readonly EvidenceProvenance[];
|
|
53
|
+
siteCenterLattice: SensorSiteCenterLatticeRegistration;
|
|
54
|
+
geometricSensitiveAperture: SensorGeometricSensitiveAperture;
|
|
55
|
+
}
|
|
56
|
+
export interface ResolveSensorSamplingApertureInput {
|
|
57
|
+
imagingArea: SensorImagingArea;
|
|
58
|
+
nativeRaster: NativeImageRaster;
|
|
59
|
+
colorSamplingProfile: SensorColorSamplingProfile;
|
|
60
|
+
colorSamplingBindingProfile: NativeEffectiveRasterColorSamplingBindingProfile;
|
|
61
|
+
samplingApertureProfile: SensorSamplingApertureProfile;
|
|
62
|
+
site: NativeColorSamplingSiteIndex;
|
|
63
|
+
}
|
|
64
|
+
export interface NativeSensorPhysicalPointMm {
|
|
65
|
+
x: number;
|
|
66
|
+
y: number;
|
|
67
|
+
}
|
|
68
|
+
export interface NativeSensorPhysicalBoundsMm {
|
|
69
|
+
left: number;
|
|
70
|
+
right: number;
|
|
71
|
+
top: number;
|
|
72
|
+
bottom: number;
|
|
73
|
+
}
|
|
74
|
+
export interface ResolvedSensorSamplingAperture {
|
|
75
|
+
profileId: string;
|
|
76
|
+
colorSamplingProfileId: string;
|
|
77
|
+
colorSamplingBindingId: string;
|
|
78
|
+
coordinateSystem: "native-sensor-physical";
|
|
79
|
+
site: NativeColorSamplingSiteIndex;
|
|
80
|
+
channelId: string;
|
|
81
|
+
siteGrid: {
|
|
82
|
+
widthSites: number;
|
|
83
|
+
heightSites: number;
|
|
84
|
+
};
|
|
85
|
+
lattice: {
|
|
86
|
+
pitchXMicrometers: number;
|
|
87
|
+
pitchYMicrometers: number;
|
|
88
|
+
firstSiteCenterFromImagingAreaTopLeftMicrometers: {
|
|
89
|
+
x: number;
|
|
90
|
+
y: number;
|
|
91
|
+
};
|
|
92
|
+
siteCenterFromImagingAreaTopLeftMicrometers: {
|
|
93
|
+
x: number;
|
|
94
|
+
y: number;
|
|
95
|
+
};
|
|
96
|
+
siteCenterFromOpticalAxisMm: NativeSensorPhysicalPointMm;
|
|
97
|
+
nominalCellAreaSquareMicrometers: number;
|
|
98
|
+
};
|
|
99
|
+
geometricSensitiveAperture: {
|
|
100
|
+
kind: "uniform-axis-aligned-rectangle";
|
|
101
|
+
widthMicrometers: number;
|
|
102
|
+
heightMicrometers: number;
|
|
103
|
+
centerOffsetFromSiteCenterMicrometers: {
|
|
104
|
+
x: number;
|
|
105
|
+
y: number;
|
|
106
|
+
};
|
|
107
|
+
centerFromOpticalAxisMm: NativeSensorPhysicalPointMm;
|
|
108
|
+
boundsFromOpticalAxisMm: NativeSensorPhysicalBoundsMm;
|
|
109
|
+
areaSquareMicrometers: number;
|
|
110
|
+
geometricSensitiveAreaFractionOfLatticeCell: number;
|
|
111
|
+
spatialWeighting: "uniform-unit-area-average";
|
|
112
|
+
neighboringGeometricApertureOverlap: "none-by-model";
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Hard scientific boundaries.
|
|
116
|
+
*/
|
|
117
|
+
sitePitchDerivedFromNativeImageRaster: false;
|
|
118
|
+
apertureDerivedFromSitePitch: false;
|
|
119
|
+
antiAliasingResponseIncluded: false;
|
|
120
|
+
microlensSpatialRedistributionIncluded: false;
|
|
121
|
+
chargeDiffusionIncluded: false;
|
|
122
|
+
electricalCrosstalkIncluded: false;
|
|
123
|
+
spectralResponseIncluded: false;
|
|
124
|
+
quantumEfficiencyIncluded: false;
|
|
125
|
+
opticalThroughputIncluded: false;
|
|
126
|
+
radiometricCollectionAreaEstablished: false;
|
|
127
|
+
physicalPhotodiodeGeometryEstablished: false;
|
|
128
|
+
provenance: {
|
|
129
|
+
profile: readonly EvidenceProvenance[];
|
|
130
|
+
lattice: readonly EvidenceProvenance[];
|
|
131
|
+
aperture: readonly EvidenceProvenance[];
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Parses physical registration of the color-site lattice plus a first geometric
|
|
136
|
+
* photosensitive-aperture model.
|
|
137
|
+
*
|
|
138
|
+
* Site-center pitch/origin are explicit facts and are never derived from
|
|
139
|
+
* NativeImageRaster. The rectangle, when resolved, is a geometric sensitive
|
|
140
|
+
* region only. It does not include microlens redirection, charge diffusion,
|
|
141
|
+
* electrical crosstalk, QE, throughput, spectral response, or an effective
|
|
142
|
+
* radiometric collection area.
|
|
143
|
+
*/
|
|
144
|
+
export declare function parseSensorSamplingApertureProfile(value: unknown): SensorSamplingApertureProfile;
|
|
145
|
+
/**
|
|
146
|
+
* Resolves one geometric sampling aperture in native sensor physical space.
|
|
147
|
+
*
|
|
148
|
+
* The result provides a normalized uniform-area spatial averaging footprint for
|
|
149
|
+
* future image sampling, plus its geometric physical area/fill-fraction
|
|
150
|
+
* diagnostics. It deliberately does not promote that geometric area into
|
|
151
|
+
* radiometric collection efficiency or physical photodiode truth.
|
|
152
|
+
*/
|
|
153
|
+
export declare function resolveSensorSamplingAperture(input: ResolveSensorSamplingApertureInput): ResolvedSensorSamplingAperture;
|
|
154
|
+
//# sourceMappingURL=sampling-aperture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sampling-aperture.d.ts","sourceRoot":"","sources":["../../src/sensor/sampling-aperture.ts"],"names":[],"mappings":"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"}
|