@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,286 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
3
|
+
import { parseEvidenceList } from "../core/evidence-provenance.js";
|
|
4
|
+
import { InvalidScientificInputError } from "../core/validation.js";
|
|
5
|
+
const COMPONENT_ROLES = new Set([
|
|
6
|
+
"cover-glass",
|
|
7
|
+
"infrared-cut",
|
|
8
|
+
"ultraviolet-cut",
|
|
9
|
+
"anti-reflection",
|
|
10
|
+
"birefringent-low-pass",
|
|
11
|
+
"wave-plate",
|
|
12
|
+
"other-optical-filter"
|
|
13
|
+
]);
|
|
14
|
+
function requireRecord(value, path) {
|
|
15
|
+
if (typeof value !== "object" ||
|
|
16
|
+
value === null ||
|
|
17
|
+
Array.isArray(value)) {
|
|
18
|
+
throw new InvalidConfigurationError(path + " must be an object.");
|
|
19
|
+
}
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
function requireNonEmptyString(value, path) {
|
|
23
|
+
if (typeof value !== "string" ||
|
|
24
|
+
value.trim().length === 0) {
|
|
25
|
+
throw new InvalidConfigurationError(path + " must be a non-empty string.");
|
|
26
|
+
}
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
function parseComponentRoles(value, path) {
|
|
30
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
31
|
+
throw new InvalidConfigurationError(path + " must be a non-empty array.");
|
|
32
|
+
}
|
|
33
|
+
const roles = value.map((entry, index) => {
|
|
34
|
+
if (typeof entry !== "string" ||
|
|
35
|
+
!COMPONENT_ROLES.has(entry)) {
|
|
36
|
+
throw new InvalidConfigurationError(path + "[" + index + "] is invalid.");
|
|
37
|
+
}
|
|
38
|
+
return entry;
|
|
39
|
+
});
|
|
40
|
+
if (new Set(roles).size !== roles.length) {
|
|
41
|
+
throw new InvalidConfigurationError(path + " must not contain duplicate roles.");
|
|
42
|
+
}
|
|
43
|
+
return roles;
|
|
44
|
+
}
|
|
45
|
+
function parseOrderedComponents(value, path) {
|
|
46
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
47
|
+
throw new InvalidConfigurationError(path + " must be a non-empty array.");
|
|
48
|
+
}
|
|
49
|
+
const components = value.map((entry, index) => {
|
|
50
|
+
const record = requireRecord(entry, path + "[" + index + "]");
|
|
51
|
+
return {
|
|
52
|
+
componentId: requireNonEmptyString(record.componentId, path + "[" + index + "].componentId"),
|
|
53
|
+
roles: parseComponentRoles(record.roles, path + "[" + index + "].roles"),
|
|
54
|
+
evidence: parseEvidenceList(record.evidence, path + "[" + index + "].evidence")
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
const ids = components.map((component) => component.componentId);
|
|
58
|
+
if (new Set(ids).size !== ids.length) {
|
|
59
|
+
throw new InvalidConfigurationError(path + " must not contain duplicate componentId values.");
|
|
60
|
+
}
|
|
61
|
+
return components;
|
|
62
|
+
}
|
|
63
|
+
function requireFiniteNumber(value, path) {
|
|
64
|
+
if (typeof value !== "number" ||
|
|
65
|
+
!Number.isFinite(value)) {
|
|
66
|
+
throw new InvalidConfigurationError(path + " must be a finite number.");
|
|
67
|
+
}
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
function parsePointSplitComponents(value, path) {
|
|
71
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
72
|
+
throw new InvalidConfigurationError(path + " must be a non-empty array.");
|
|
73
|
+
}
|
|
74
|
+
const components = value.map((entry, index) => {
|
|
75
|
+
const record = requireRecord(entry, path + "[" + index + "]");
|
|
76
|
+
const offset = requireRecord(record.offsetMicrometers, path + "[" + index + "].offsetMicrometers");
|
|
77
|
+
const normalizedWeight = requireFiniteNumber(record.normalizedWeight, path + "[" + index + "].normalizedWeight");
|
|
78
|
+
if (normalizedWeight <= 0) {
|
|
79
|
+
throw new InvalidConfigurationError(path +
|
|
80
|
+
"[" +
|
|
81
|
+
index +
|
|
82
|
+
"].normalizedWeight must be greater than zero.");
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
offsetMicrometers: {
|
|
86
|
+
x: requireFiniteNumber(offset.x, path +
|
|
87
|
+
"[" +
|
|
88
|
+
index +
|
|
89
|
+
"].offsetMicrometers.x"),
|
|
90
|
+
y: requireFiniteNumber(offset.y, path +
|
|
91
|
+
"[" +
|
|
92
|
+
index +
|
|
93
|
+
"].offsetMicrometers.y")
|
|
94
|
+
},
|
|
95
|
+
normalizedWeight
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
const weightSum = components.reduce((sum, component) => sum + component.normalizedWeight, 0);
|
|
99
|
+
if (!Number.isFinite(weightSum) ||
|
|
100
|
+
Math.abs(weightSum - 1) > 1e-12) {
|
|
101
|
+
throw new InvalidConfigurationError(path +
|
|
102
|
+
" normalizedWeight values must sum to 1 within 1e-12.");
|
|
103
|
+
}
|
|
104
|
+
return components;
|
|
105
|
+
}
|
|
106
|
+
function parseAntiAliasingResponse(value, path) {
|
|
107
|
+
const record = requireRecord(value, path);
|
|
108
|
+
if (record.kind === "absent" ||
|
|
109
|
+
record.kind === "present-unresolved") {
|
|
110
|
+
if (record.coordinateSystem !== undefined ||
|
|
111
|
+
record.scope !== undefined ||
|
|
112
|
+
record.components !== undefined) {
|
|
113
|
+
throw new InvalidConfigurationError(path +
|
|
114
|
+
" absent/present-unresolved responses must omit kernel fields.");
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
kind: record.kind,
|
|
118
|
+
evidence: parseEvidenceList(record.evidence, path + ".evidence")
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (record.kind ===
|
|
122
|
+
"normalized-point-splitting-kernel") {
|
|
123
|
+
if (record.coordinateSystem !==
|
|
124
|
+
"native-sensor-physical") {
|
|
125
|
+
throw new InvalidConfigurationError(path +
|
|
126
|
+
'.coordinateSystem must be "native-sensor-physical".');
|
|
127
|
+
}
|
|
128
|
+
if (record.scope !==
|
|
129
|
+
"field-wavelength-polarization-invariant-approximation") {
|
|
130
|
+
throw new InvalidConfigurationError(path + ".scope is invalid.");
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
kind: "normalized-point-splitting-kernel",
|
|
134
|
+
evidence: parseEvidenceList(record.evidence, path + ".evidence"),
|
|
135
|
+
coordinateSystem: "native-sensor-physical",
|
|
136
|
+
scope: "field-wavelength-polarization-invariant-approximation",
|
|
137
|
+
components: parsePointSplitComponents(record.components, path + ".components")
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
throw new InvalidConfigurationError(path + ".kind is invalid.");
|
|
141
|
+
}
|
|
142
|
+
function parseMicrolens(value, path) {
|
|
143
|
+
const record = requireRecord(value, path);
|
|
144
|
+
if (record.presence !== "present" &&
|
|
145
|
+
record.presence !== "absent") {
|
|
146
|
+
throw new InvalidConfigurationError(path + ".presence is invalid.");
|
|
147
|
+
}
|
|
148
|
+
if (record.opticalEffectModel !== "unresolved") {
|
|
149
|
+
throw new InvalidConfigurationError(path +
|
|
150
|
+
'.opticalEffectModel must be "unresolved" in schema 0.1.0.');
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
presence: record.presence,
|
|
154
|
+
evidence: parseEvidenceList(record.evidence, path + ".evidence"),
|
|
155
|
+
opticalEffectModel: "unresolved"
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Parses descriptive sensor optical-stack metadata plus an optional explicitly
|
|
160
|
+
* declared effective anti-aliasing spatial response.
|
|
161
|
+
*
|
|
162
|
+
* Unknown facts are omitted instead of inferred. Physical component presence
|
|
163
|
+
* is intentionally separate from effective anti-aliasing response so the
|
|
164
|
+
* schema can represent cancellation/neutralization designs without claiming
|
|
165
|
+
* the physical assembly is absent.
|
|
166
|
+
*
|
|
167
|
+
* Cover/filter-stack and microlens presence do not create optical effects in
|
|
168
|
+
* schema 0.1.0. Thickness, refractive index, spectral transmission, angular
|
|
169
|
+
* acceptance, focus shift and microlens collection behavior require later
|
|
170
|
+
* explicit models/calibration.
|
|
171
|
+
*/
|
|
172
|
+
export function parseSensorOpticalStackProfile(value) {
|
|
173
|
+
const profile = requireRecord(value, "sensorOpticalStack");
|
|
174
|
+
if (profile.schemaVersion !== "0.1.0") {
|
|
175
|
+
throw new InvalidConfigurationError('sensorOpticalStack.schemaVersion must be "0.1.0".');
|
|
176
|
+
}
|
|
177
|
+
const orderedComponents = profile.orderedComponents === undefined
|
|
178
|
+
? undefined
|
|
179
|
+
: parseOrderedComponents(profile.orderedComponents, "sensorOpticalStack.orderedComponents");
|
|
180
|
+
const effectiveAntiAliasingSpatialResponse = profile.effectiveAntiAliasingSpatialResponse ===
|
|
181
|
+
undefined
|
|
182
|
+
? undefined
|
|
183
|
+
: parseAntiAliasingResponse(profile.effectiveAntiAliasingSpatialResponse, "sensorOpticalStack.effectiveAntiAliasingSpatialResponse");
|
|
184
|
+
const microlens = profile.microlens === undefined
|
|
185
|
+
? undefined
|
|
186
|
+
: parseMicrolens(profile.microlens, "sensorOpticalStack.microlens");
|
|
187
|
+
if (orderedComponents === undefined &&
|
|
188
|
+
effectiveAntiAliasingSpatialResponse ===
|
|
189
|
+
undefined &&
|
|
190
|
+
microlens === undefined) {
|
|
191
|
+
throw new InvalidConfigurationError("sensorOpticalStack must assert at least one optical-stack fact.");
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
schemaVersion: "0.1.0",
|
|
195
|
+
profileId: requireNonEmptyString(profile.profileId, "sensorOpticalStack.profileId"),
|
|
196
|
+
evidence: parseEvidenceList(profile.evidence, "sensorOpticalStack.evidence"),
|
|
197
|
+
...(orderedComponents === undefined
|
|
198
|
+
? {}
|
|
199
|
+
: { orderedComponents }),
|
|
200
|
+
...(effectiveAntiAliasingSpatialResponse ===
|
|
201
|
+
undefined
|
|
202
|
+
? {}
|
|
203
|
+
: {
|
|
204
|
+
effectiveAntiAliasingSpatialResponse
|
|
205
|
+
}),
|
|
206
|
+
...(microlens === undefined
|
|
207
|
+
? {}
|
|
208
|
+
: { microlens })
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Resolves only the effective anti-aliasing spatial kernel.
|
|
213
|
+
*
|
|
214
|
+
* This is not a whole optical-stack PSF. Cover/filter transmission, refraction,
|
|
215
|
+
* microlens behavior, field/wavelength/polarization dependence, and total
|
|
216
|
+
* throughput remain excluded.
|
|
217
|
+
*
|
|
218
|
+
* A documented absent effective anti-aliasing response resolves to an identity
|
|
219
|
+
* component at zero offset. An unknown response (field omitted) or a
|
|
220
|
+
* present-but-unresolved response fails closed.
|
|
221
|
+
*/
|
|
222
|
+
export function resolveAntiAliasingSpatialKernel(profileInput) {
|
|
223
|
+
const profile = parseSensorOpticalStackProfile(profileInput);
|
|
224
|
+
const response = profile.effectiveAntiAliasingSpatialResponse;
|
|
225
|
+
if (response === undefined) {
|
|
226
|
+
throw new InvalidScientificInputError("Effective anti-aliasing spatial response is unknown/unasserted for this optical-stack profile.");
|
|
227
|
+
}
|
|
228
|
+
if (response.kind === "present-unresolved") {
|
|
229
|
+
throw new InvalidScientificInputError("Effective anti-aliasing spatial response is present but unresolved; a spatial kernel cannot be produced.");
|
|
230
|
+
}
|
|
231
|
+
if (response.kind === "absent") {
|
|
232
|
+
return {
|
|
233
|
+
profileId: profile.profileId,
|
|
234
|
+
effectiveResponse: "absent",
|
|
235
|
+
coordinateSystem: "native-sensor-physical",
|
|
236
|
+
components: [
|
|
237
|
+
{
|
|
238
|
+
offsetMicrometers: {
|
|
239
|
+
x: 0,
|
|
240
|
+
y: 0
|
|
241
|
+
},
|
|
242
|
+
normalizedWeight: 1
|
|
243
|
+
}
|
|
244
|
+
],
|
|
245
|
+
normalizedWeightSum: 1,
|
|
246
|
+
throughputIncluded: false,
|
|
247
|
+
spectralTransmissionIncluded: false,
|
|
248
|
+
fieldDependenceIncluded: false,
|
|
249
|
+
wavelengthDependenceIncluded: false,
|
|
250
|
+
polarizationDependenceIncluded: false,
|
|
251
|
+
microlensResponseIncluded: false,
|
|
252
|
+
coverFilterStackEffectsIncluded: false,
|
|
253
|
+
wholeSensorOpticalStackResponse: false,
|
|
254
|
+
provenance: {
|
|
255
|
+
profile: profile.evidence,
|
|
256
|
+
antiAliasingResponse: response.evidence
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
const normalizedWeightSum = response.components.reduce((sum, component) => sum + component.normalizedWeight, 0);
|
|
261
|
+
return {
|
|
262
|
+
profileId: profile.profileId,
|
|
263
|
+
effectiveResponse: "normalized-point-splitting-kernel",
|
|
264
|
+
coordinateSystem: "native-sensor-physical",
|
|
265
|
+
components: response.components.map((component) => ({
|
|
266
|
+
offsetMicrometers: {
|
|
267
|
+
...component.offsetMicrometers
|
|
268
|
+
},
|
|
269
|
+
normalizedWeight: component.normalizedWeight
|
|
270
|
+
})),
|
|
271
|
+
normalizedWeightSum,
|
|
272
|
+
throughputIncluded: false,
|
|
273
|
+
spectralTransmissionIncluded: false,
|
|
274
|
+
fieldDependenceIncluded: false,
|
|
275
|
+
wavelengthDependenceIncluded: false,
|
|
276
|
+
polarizationDependenceIncluded: false,
|
|
277
|
+
microlensResponseIncluded: false,
|
|
278
|
+
coverFilterStackEffectsIncluded: false,
|
|
279
|
+
wholeSensorOpticalStackResponse: false,
|
|
280
|
+
provenance: {
|
|
281
|
+
profile: profile.evidence,
|
|
282
|
+
antiAliasingResponse: response.evidence
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=optical-stack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"optical-stack.js","sourceRoot":"","sources":["../../src/sensor/optical-stack.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { type CalculationProvenance, type CalculationResult } from "../core/calculation-result.js";
|
|
2
|
+
import { type EvidenceProvenance } from "../core/evidence-provenance.js";
|
|
3
|
+
import type { RasterPoint, RasterRect } from "../output/capture-geometry.js";
|
|
4
|
+
import { type ExposureBoundarySchedule, type SourcedCaptureTimingSeconds } from "./exposure-window.js";
|
|
5
|
+
import { type CaptureShutterMechanism, type NativeSensorReadoutScanDirection, type SensorReadoutTimingDeclaration, type SourcedSensorTimingSeconds } from "./readout-timing.js";
|
|
6
|
+
import type { NativeImageRaster } from "./sensor-geometry.js";
|
|
7
|
+
export type ReadoutExposureBoundaryId = "opening" | "closing";
|
|
8
|
+
export type ReadoutExposureSpatialPhaseOrientation = "same" | "reversed";
|
|
9
|
+
export interface ReadoutExposureBoundarySpatialLink {
|
|
10
|
+
boundary: ReadoutExposureBoundaryId;
|
|
11
|
+
/**
|
|
12
|
+
* Relationship between normalized rolling-readout scan phase and the
|
|
13
|
+
* selected electronic exposure-boundary scan phase.
|
|
14
|
+
*
|
|
15
|
+
* "same": boundary normalized phase = readout normalized phase.
|
|
16
|
+
* "reversed": boundary normalized phase = 1 - readout normalized phase.
|
|
17
|
+
*
|
|
18
|
+
* This does not establish absolute temporal synchronization.
|
|
19
|
+
*/
|
|
20
|
+
phaseOrientation: ReadoutExposureSpatialPhaseOrientation;
|
|
21
|
+
/**
|
|
22
|
+
* Evidence supporting the relationship itself.
|
|
23
|
+
*
|
|
24
|
+
* The readout direction/timing and exposure-boundary direction/timing retain
|
|
25
|
+
* their own separate evidence.
|
|
26
|
+
*/
|
|
27
|
+
evidence: readonly EvidenceProvenance[];
|
|
28
|
+
}
|
|
29
|
+
export type ReadoutExposureTimingLinkageDeclaration = {
|
|
30
|
+
/**
|
|
31
|
+
* Photivra asserts no readout↔exposure relationship for this capture.
|
|
32
|
+
* This is not evidence that the physical processes are independent.
|
|
33
|
+
*/
|
|
34
|
+
kind: "unlinked";
|
|
35
|
+
links?: never;
|
|
36
|
+
} | {
|
|
37
|
+
/**
|
|
38
|
+
* One or more exposure boundaries are explicitly related to rolling
|
|
39
|
+
* readout by normalized native-sensor spatial phase.
|
|
40
|
+
*/
|
|
41
|
+
kind: "spatial-phase-linked";
|
|
42
|
+
links: readonly ReadoutExposureBoundarySpatialLink[];
|
|
43
|
+
};
|
|
44
|
+
export interface AssessReadoutExposureTimingLinkageInput {
|
|
45
|
+
nativeRaster: NativeImageRaster;
|
|
46
|
+
activeCaptureRect?: RasterRect;
|
|
47
|
+
shutterMechanism: CaptureShutterMechanism;
|
|
48
|
+
readout: SensorReadoutTimingDeclaration;
|
|
49
|
+
nominalExposureDurationSeconds: SourcedCaptureTimingSeconds;
|
|
50
|
+
opening: ExposureBoundarySchedule;
|
|
51
|
+
closing: ExposureBoundarySchedule;
|
|
52
|
+
linkage: ReadoutExposureTimingLinkageDeclaration;
|
|
53
|
+
samplePointsNative?: readonly RasterPoint[];
|
|
54
|
+
}
|
|
55
|
+
export interface ReadoutExposureBoundarySpatialLinkAssessment {
|
|
56
|
+
boundary: ReadoutExposureBoundaryId;
|
|
57
|
+
boundaryActuator: "electronic";
|
|
58
|
+
phaseOrientation: ReadoutExposureSpatialPhaseOrientation;
|
|
59
|
+
normalizedPhaseRelationship: "boundary-phase-equals-readout-phase" | "boundary-phase-equals-one-minus-readout-phase";
|
|
60
|
+
relationshipEvidence: readonly EvidenceProvenance[];
|
|
61
|
+
readoutDirectionNative: NativeSensorReadoutScanDirection;
|
|
62
|
+
boundaryDirectionNative: NativeSensorReadoutScanDirection;
|
|
63
|
+
/**
|
|
64
|
+
* First-to-last rolling sensor spatial sampling skew.
|
|
65
|
+
*/
|
|
66
|
+
readoutSpatialSamplingSkewSeconds: SourcedSensorTimingSeconds;
|
|
67
|
+
/**
|
|
68
|
+
* First-to-last exposure-boundary traversal duration.
|
|
69
|
+
*/
|
|
70
|
+
boundaryTraversalDurationSeconds: SourcedCaptureTimingSeconds;
|
|
71
|
+
/**
|
|
72
|
+
* Derived descriptive ratio only. A value of 1 does not prove temporal
|
|
73
|
+
* synchronization or a common clock origin.
|
|
74
|
+
*/
|
|
75
|
+
boundaryTraversalToReadoutSpatialSkewRatio: number;
|
|
76
|
+
absoluteTemporalAlignment: "not-established";
|
|
77
|
+
}
|
|
78
|
+
export interface ReadoutExposureTimingLinkageAssessment {
|
|
79
|
+
linkageKind: ReadoutExposureTimingLinkageDeclaration["kind"];
|
|
80
|
+
relationshipMeaning: "no-readout-exposure-relationship-asserted" | "normalized-spatial-phase-relationship-asserted";
|
|
81
|
+
readoutMode: "rolling" | "global";
|
|
82
|
+
shutterMechanism: CaptureShutterMechanism;
|
|
83
|
+
activeCaptureRect: RasterRect;
|
|
84
|
+
absoluteTemporalAlignment: "not-established";
|
|
85
|
+
/**
|
|
86
|
+
* Capture data-readout duration is preserved for diagnostics but is not used
|
|
87
|
+
* to validate any exposure-boundary linkage.
|
|
88
|
+
*/
|
|
89
|
+
captureReadoutDurationSeconds: SourcedSensorTimingSeconds;
|
|
90
|
+
links: readonly ReadoutExposureBoundarySpatialLinkAssessment[];
|
|
91
|
+
componentProvenance: {
|
|
92
|
+
sensorReadout: CalculationProvenance;
|
|
93
|
+
exposureWindows: CalculationProvenance;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Assesses an explicitly declared relationship between rolling sensor readout
|
|
98
|
+
* spatial phase and one or more electronic exposure-boundary scans.
|
|
99
|
+
*
|
|
100
|
+
* This contract is deliberately weaker than temporal synchronization. It can
|
|
101
|
+
* establish that two schedules traverse the same native spatial phase ordering
|
|
102
|
+
* (or its reverse), but it does not establish when sensor data readout occurs
|
|
103
|
+
* relative to exposure start/end.
|
|
104
|
+
*
|
|
105
|
+
* The total capture data-readout duration is preserved diagnostically and is
|
|
106
|
+
* never used to validate the relationship. Different rolling-readout spatial
|
|
107
|
+
* skew and exposure-boundary traversal durations are allowed; their ratio is
|
|
108
|
+
* reported without implying a shared clock origin.
|
|
109
|
+
*/
|
|
110
|
+
export declare function assessReadoutExposureTimingLinkage(input: AssessReadoutExposureTimingLinkageInput): CalculationResult<ReadoutExposureTimingLinkageAssessment>;
|
|
111
|
+
//# sourceMappingURL=readout-exposure-linkage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readout-exposure-linkage.d.ts","sourceRoot":"","sources":["../../src/sensor/readout-exposure-linkage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,210 @@
|
|
|
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 } from "../core/validation.js";
|
|
5
|
+
import { calculateCaptureExposureWindows } from "./exposure-window.js";
|
|
6
|
+
import { calculateSensorReadoutTiming } from "./readout-timing.js";
|
|
7
|
+
const BOUNDARIES = new Set([
|
|
8
|
+
"opening",
|
|
9
|
+
"closing"
|
|
10
|
+
]);
|
|
11
|
+
const PHASE_ORIENTATIONS = new Set([
|
|
12
|
+
"same",
|
|
13
|
+
"reversed"
|
|
14
|
+
]);
|
|
15
|
+
function requireRecord(value, path) {
|
|
16
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
17
|
+
throw new InvalidScientificInputError(path + " must be an object.");
|
|
18
|
+
}
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
function parseSpatialLink(value, path) {
|
|
22
|
+
const record = requireRecord(value, path);
|
|
23
|
+
if (typeof record.boundary !== "string" ||
|
|
24
|
+
!BOUNDARIES.has(record.boundary)) {
|
|
25
|
+
throw new InvalidScientificInputError(path + ".boundary is invalid.");
|
|
26
|
+
}
|
|
27
|
+
if (typeof record.phaseOrientation !== "string" ||
|
|
28
|
+
!PHASE_ORIENTATIONS.has(record.phaseOrientation)) {
|
|
29
|
+
throw new InvalidScientificInputError(path + ".phaseOrientation is invalid.");
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
boundary: record.boundary,
|
|
33
|
+
phaseOrientation: record.phaseOrientation,
|
|
34
|
+
evidence: parseEvidenceList(record.evidence, path + ".evidence")
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function parseLinkageDeclaration(value) {
|
|
38
|
+
const record = requireRecord(value, "linkage");
|
|
39
|
+
if (record.kind === "unlinked") {
|
|
40
|
+
if (record.links !== undefined) {
|
|
41
|
+
throw new InvalidScientificInputError("linkage.links must be omitted when linkage.kind is unlinked.");
|
|
42
|
+
}
|
|
43
|
+
return { kind: "unlinked" };
|
|
44
|
+
}
|
|
45
|
+
if (record.kind !== "spatial-phase-linked") {
|
|
46
|
+
throw new InvalidScientificInputError("linkage.kind is invalid.");
|
|
47
|
+
}
|
|
48
|
+
if (!Array.isArray(record.links) || record.links.length === 0) {
|
|
49
|
+
throw new InvalidScientificInputError("linkage.links must be a non-empty array for spatial-phase-linked linkage.");
|
|
50
|
+
}
|
|
51
|
+
const links = record.links.map((entry, index) => parseSpatialLink(entry, "linkage.links[" + index + "]"));
|
|
52
|
+
const seen = new Set();
|
|
53
|
+
for (const link of links) {
|
|
54
|
+
if (seen.has(link.boundary)) {
|
|
55
|
+
throw new InvalidScientificInputError("linkage.links must not contain duplicate boundary links.");
|
|
56
|
+
}
|
|
57
|
+
seen.add(link.boundary);
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
kind: "spatial-phase-linked",
|
|
61
|
+
links
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function oppositeDirection(direction) {
|
|
65
|
+
switch (direction) {
|
|
66
|
+
case "top-to-bottom":
|
|
67
|
+
return "bottom-to-top";
|
|
68
|
+
case "bottom-to-top":
|
|
69
|
+
return "top-to-bottom";
|
|
70
|
+
case "left-to-right":
|
|
71
|
+
return "right-to-left";
|
|
72
|
+
case "right-to-left":
|
|
73
|
+
return "left-to-right";
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function expectedBoundaryDirection(readoutDirection, phaseOrientation) {
|
|
77
|
+
return phaseOrientation === "same"
|
|
78
|
+
? readoutDirection
|
|
79
|
+
: oppositeDirection(readoutDirection);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Assesses an explicitly declared relationship between rolling sensor readout
|
|
83
|
+
* spatial phase and one or more electronic exposure-boundary scans.
|
|
84
|
+
*
|
|
85
|
+
* This contract is deliberately weaker than temporal synchronization. It can
|
|
86
|
+
* establish that two schedules traverse the same native spatial phase ordering
|
|
87
|
+
* (or its reverse), but it does not establish when sensor data readout occurs
|
|
88
|
+
* relative to exposure start/end.
|
|
89
|
+
*
|
|
90
|
+
* The total capture data-readout duration is preserved diagnostically and is
|
|
91
|
+
* never used to validate the relationship. Different rolling-readout spatial
|
|
92
|
+
* skew and exposure-boundary traversal durations are allowed; their ratio is
|
|
93
|
+
* reported without implying a shared clock origin.
|
|
94
|
+
*/
|
|
95
|
+
export function assessReadoutExposureTimingLinkage(input) {
|
|
96
|
+
const linkage = parseLinkageDeclaration(input.linkage);
|
|
97
|
+
const sensorReadout = calculateSensorReadoutTiming({
|
|
98
|
+
nativeRaster: input.nativeRaster,
|
|
99
|
+
...(input.activeCaptureRect === undefined
|
|
100
|
+
? {}
|
|
101
|
+
: { activeCaptureRect: input.activeCaptureRect }),
|
|
102
|
+
shutterMechanism: input.shutterMechanism,
|
|
103
|
+
readout: input.readout,
|
|
104
|
+
...(input.samplePointsNative === undefined
|
|
105
|
+
? {}
|
|
106
|
+
: { samplePointsNative: input.samplePointsNative })
|
|
107
|
+
});
|
|
108
|
+
const exposureWindows = calculateCaptureExposureWindows({
|
|
109
|
+
nativeRaster: input.nativeRaster,
|
|
110
|
+
...(input.activeCaptureRect === undefined
|
|
111
|
+
? {}
|
|
112
|
+
: { activeCaptureRect: input.activeCaptureRect }),
|
|
113
|
+
shutterMechanism: input.shutterMechanism,
|
|
114
|
+
nominalExposureDurationSeconds: input.nominalExposureDurationSeconds,
|
|
115
|
+
opening: input.opening,
|
|
116
|
+
closing: input.closing,
|
|
117
|
+
...(input.samplePointsNative === undefined
|
|
118
|
+
? {}
|
|
119
|
+
: { samplePointsNative: input.samplePointsNative })
|
|
120
|
+
});
|
|
121
|
+
if (linkage.kind === "unlinked") {
|
|
122
|
+
return approximationResult({
|
|
123
|
+
linkageKind: "unlinked",
|
|
124
|
+
relationshipMeaning: "no-readout-exposure-relationship-asserted",
|
|
125
|
+
readoutMode: sensorReadout.value.readoutMode,
|
|
126
|
+
shutterMechanism: input.shutterMechanism,
|
|
127
|
+
activeCaptureRect: {
|
|
128
|
+
...sensorReadout.value.activeCaptureRect
|
|
129
|
+
},
|
|
130
|
+
absoluteTemporalAlignment: "not-established",
|
|
131
|
+
captureReadoutDurationSeconds: sensorReadout.value.captureReadoutDurationSeconds,
|
|
132
|
+
links: [],
|
|
133
|
+
componentProvenance: {
|
|
134
|
+
sensorReadout: sensorReadout.provenance,
|
|
135
|
+
exposureWindows: exposureWindows.provenance
|
|
136
|
+
}
|
|
137
|
+
}, "readout-exposure-spatial-linkage", "1.0.0", [
|
|
138
|
+
"Unlinked means Photivra asserts no readout-to-exposure relationship for this capture; it does not prove the physical processes are independent.",
|
|
139
|
+
"Sensor data-readout timing and exposure-window timing retain independent provenance and semantics.",
|
|
140
|
+
"Absolute temporal alignment between data readout and exposure boundaries is not established."
|
|
141
|
+
]);
|
|
142
|
+
}
|
|
143
|
+
const readoutScan = sensorReadout.value.scan;
|
|
144
|
+
if (readoutScan === null) {
|
|
145
|
+
throw new InvalidScientificInputError("spatial-phase-linked linkage requires rolling sensor readout with a spatial scan.");
|
|
146
|
+
}
|
|
147
|
+
const assessments = linkage.links.map((link) => {
|
|
148
|
+
const boundary = link.boundary === "opening"
|
|
149
|
+
? exposureWindows.value.opening
|
|
150
|
+
: exposureWindows.value.closing;
|
|
151
|
+
if (boundary.actuator !== "electronic") {
|
|
152
|
+
throw new InvalidScientificInputError("A readout spatial-phase link may target only an electronic exposure boundary.");
|
|
153
|
+
}
|
|
154
|
+
if (boundary.schedule.kind !==
|
|
155
|
+
"uniform-linear-native-scan") {
|
|
156
|
+
throw new InvalidScientificInputError("A readout spatial-phase link requires the selected exposure boundary to use a uniform-linear native scan.");
|
|
157
|
+
}
|
|
158
|
+
const readoutDirection = readoutScan.directionNative.value;
|
|
159
|
+
const boundaryDirection = boundary.schedule.directionNative.value;
|
|
160
|
+
const expectedDirection = expectedBoundaryDirection(readoutDirection, link.phaseOrientation);
|
|
161
|
+
if (boundaryDirection !== expectedDirection) {
|
|
162
|
+
throw new InvalidScientificInputError("Declared readout/exposure spatial phase orientation contradicts the readout and exposure-boundary scan directions.");
|
|
163
|
+
}
|
|
164
|
+
const readoutSpatialSamplingSkewSeconds = readoutScan.spatialSamplingSkewSeconds;
|
|
165
|
+
const boundaryTraversalDurationSeconds = boundary.schedule.traversalDurationSeconds;
|
|
166
|
+
return {
|
|
167
|
+
boundary: link.boundary,
|
|
168
|
+
boundaryActuator: "electronic",
|
|
169
|
+
phaseOrientation: link.phaseOrientation,
|
|
170
|
+
normalizedPhaseRelationship: link.phaseOrientation === "same"
|
|
171
|
+
? "boundary-phase-equals-readout-phase"
|
|
172
|
+
: "boundary-phase-equals-one-minus-readout-phase",
|
|
173
|
+
relationshipEvidence: link.evidence,
|
|
174
|
+
readoutDirectionNative: readoutDirection,
|
|
175
|
+
boundaryDirectionNative: boundaryDirection,
|
|
176
|
+
readoutSpatialSamplingSkewSeconds,
|
|
177
|
+
boundaryTraversalDurationSeconds,
|
|
178
|
+
boundaryTraversalToReadoutSpatialSkewRatio: boundaryTraversalDurationSeconds.value /
|
|
179
|
+
readoutSpatialSamplingSkewSeconds.value,
|
|
180
|
+
absoluteTemporalAlignment: "not-established"
|
|
181
|
+
};
|
|
182
|
+
});
|
|
183
|
+
return approximationResult({
|
|
184
|
+
linkageKind: "spatial-phase-linked",
|
|
185
|
+
relationshipMeaning: "normalized-spatial-phase-relationship-asserted",
|
|
186
|
+
readoutMode: sensorReadout.value.readoutMode,
|
|
187
|
+
shutterMechanism: input.shutterMechanism,
|
|
188
|
+
activeCaptureRect: {
|
|
189
|
+
...sensorReadout.value.activeCaptureRect
|
|
190
|
+
},
|
|
191
|
+
absoluteTemporalAlignment: "not-established",
|
|
192
|
+
captureReadoutDurationSeconds: sensorReadout.value.captureReadoutDurationSeconds,
|
|
193
|
+
links: assessments,
|
|
194
|
+
componentProvenance: {
|
|
195
|
+
sensorReadout: sensorReadout.provenance,
|
|
196
|
+
exposureWindows: exposureWindows.provenance
|
|
197
|
+
}
|
|
198
|
+
}, "readout-exposure-spatial-linkage", "1.0.0", [
|
|
199
|
+
"The linkage establishes normalized native-sensor spatial phase/order only, not absolute temporal synchronization.",
|
|
200
|
+
"Every asserted boundary link carries evidence separate from the evidence for the underlying readout and exposure timing facts.",
|
|
201
|
+
"Only electronic exposure boundaries may be linked to rolling sensor readout spatial phase.",
|
|
202
|
+
"Same phase orientation requires matching native scan direction; reversed phase orientation requires the exact opposite direction on the same native axis.",
|
|
203
|
+
"Rolling readout spatial skew and exposure-boundary traversal duration may differ; their ratio is descriptive and does not establish a common clock origin.",
|
|
204
|
+
"Capture data-readout duration is not used to validate exposure-boundary timing linkage.",
|
|
205
|
+
"Active capture, native coordinate semantics and shutter mechanism are shared because both component schedules are resolved from the same input.",
|
|
206
|
+
"Sensor readout and exposure-window component provenance remain visible; linkage does not upgrade either component to calibrated status.",
|
|
207
|
+
"No camera-specific timing relationship is inferred from shutter mechanism, sensor architecture metadata, output resolution or adjacent specifications."
|
|
208
|
+
]);
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=readout-exposure-linkage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readout-exposure-linkage.js","sourceRoot":"","sources":["../../src/sensor/readout-exposure-linkage.ts"],"names":[],"mappings":"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"}
|