@photivra/engine 0.2.0 → 0.5.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.
Files changed (89) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/CITATION.cff +1 -1
  3. package/README.md +59 -10
  4. package/dist/camera/equivalent-focal-length.d.ts +34 -0
  5. package/dist/camera/equivalent-focal-length.d.ts.map +1 -0
  6. package/dist/camera/equivalent-focal-length.js +33 -0
  7. package/dist/camera/equivalent-focal-length.js.map +1 -0
  8. package/dist/camera/field-of-view.d.ts +40 -3
  9. package/dist/camera/field-of-view.d.ts.map +1 -1
  10. package/dist/camera/field-of-view.js +66 -24
  11. package/dist/camera/field-of-view.js.map +1 -1
  12. package/dist/core/calculation-result.d.ts.map +1 -1
  13. package/dist/core/calculation-result.js +14 -2
  14. package/dist/core/calculation-result.js.map +1 -1
  15. package/dist/core/configuration-error.d.ts +9 -0
  16. package/dist/core/configuration-error.d.ts.map +1 -0
  17. package/dist/core/configuration-error.js +13 -0
  18. package/dist/core/configuration-error.js.map +1 -0
  19. package/dist/core/evidence-provenance.d.ts +40 -0
  20. package/dist/core/evidence-provenance.d.ts.map +1 -0
  21. package/dist/core/evidence-provenance.js +79 -0
  22. package/dist/core/evidence-provenance.js.map +1 -0
  23. package/dist/core/image-formation.d.ts +70 -0
  24. package/dist/core/image-formation.d.ts.map +1 -0
  25. package/dist/core/image-formation.js +335 -0
  26. package/dist/core/image-formation.js.map +1 -0
  27. package/dist/index.d.ts +15 -3
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +15 -3
  30. package/dist/index.js.map +1 -1
  31. package/dist/motion/camera-rotation.d.ts +91 -0
  32. package/dist/motion/camera-rotation.d.ts.map +1 -0
  33. package/dist/motion/camera-rotation.js +157 -0
  34. package/dist/motion/camera-rotation.js.map +1 -0
  35. package/dist/optics/focus-breathing.d.ts +73 -0
  36. package/dist/optics/focus-breathing.d.ts.map +1 -0
  37. package/dist/optics/focus-breathing.js +77 -0
  38. package/dist/optics/focus-breathing.js.map +1 -0
  39. package/dist/optics/illumination-vignetting.d.ts +59 -0
  40. package/dist/optics/illumination-vignetting.d.ts.map +1 -0
  41. package/dist/optics/illumination-vignetting.js +107 -0
  42. package/dist/optics/illumination-vignetting.js.map +1 -0
  43. package/dist/optics/lateral-chromatic-aberration.d.ts +117 -0
  44. package/dist/optics/lateral-chromatic-aberration.d.ts.map +1 -0
  45. package/dist/optics/lateral-chromatic-aberration.js +228 -0
  46. package/dist/optics/lateral-chromatic-aberration.js.map +1 -0
  47. package/dist/optics/psf-foundation.d.ts +102 -0
  48. package/dist/optics/psf-foundation.d.ts.map +1 -0
  49. package/dist/optics/psf-foundation.js +164 -0
  50. package/dist/optics/psf-foundation.js.map +1 -0
  51. package/dist/optics/radial-distortion.d.ts +131 -0
  52. package/dist/optics/radial-distortion.d.ts.map +1 -0
  53. package/dist/optics/radial-distortion.js +227 -0
  54. package/dist/optics/radial-distortion.js.map +1 -0
  55. package/dist/output/capture-geometry.d.ts +278 -0
  56. package/dist/output/capture-geometry.d.ts.map +1 -0
  57. package/dist/output/capture-geometry.js +562 -0
  58. package/dist/output/capture-geometry.js.map +1 -0
  59. package/dist/schema/validation.d.ts +1 -8
  60. package/dist/schema/validation.d.ts.map +1 -1
  61. package/dist/schema/validation.js +2 -11
  62. package/dist/schema/validation.js.map +1 -1
  63. package/dist/sensor/architecture.d.ts +40 -0
  64. package/dist/sensor/architecture.d.ts.map +1 -0
  65. package/dist/sensor/architecture.js +98 -0
  66. package/dist/sensor/architecture.js.map +1 -0
  67. package/dist/sensor/radiometry-readiness.d.ts +111 -0
  68. package/dist/sensor/radiometry-readiness.d.ts.map +1 -0
  69. package/dist/sensor/radiometry-readiness.js +294 -0
  70. package/dist/sensor/radiometry-readiness.js.map +1 -0
  71. package/dist/sensor/sensor-geometry.d.ts +99 -0
  72. package/dist/sensor/sensor-geometry.d.ts.map +1 -0
  73. package/dist/sensor/sensor-geometry.js +71 -0
  74. package/dist/sensor/sensor-geometry.js.map +1 -0
  75. package/dist/simulation/poc-simulation.d.ts +93 -1
  76. package/dist/simulation/poc-simulation.d.ts.map +1 -1
  77. package/dist/simulation/poc-simulation.js +308 -24
  78. package/dist/simulation/poc-simulation.js.map +1 -1
  79. package/docs/API_STYLE.md +36 -2
  80. package/docs/ARCHITECTURE.md +179 -1
  81. package/docs/IMAGE_FORMATION.md +151 -0
  82. package/docs/MOTION_AND_SIGNAL.md +52 -1
  83. package/docs/PHYSICS_FOUNDATION.md +190 -3
  84. package/docs/POC_API.md +73 -7
  85. package/docs/PROVENANCE.md +24 -0
  86. package/docs/PSF_FOUNDATION.md +133 -0
  87. package/docs/STABILIZATION.md +17 -4
  88. package/docs/USAGE.md +714 -3
  89. package/package.json +3 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"illumination-vignetting.js","sourceRoot":"","sources":["../../src/optics/illumination-vignetting.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ import { type CalculationResult } from "../core/calculation-result.js";
2
+ import { type LensFieldPointMm, type RadialDistortionCoefficients } from "./radial-distortion.js";
3
+ export type LateralChromaticAberrationChannel = "red" | "green" | "blue";
4
+ export interface LateralChromaticAberrationProfile {
5
+ /** Shared physical image-plane normalization radius in millimetres. */
6
+ normalizationRadiusMm: number;
7
+ /** Shared undistorted normalized-radius operating envelope. */
8
+ maximumNormalizedRadius: number;
9
+ /**
10
+ * Green-reference base geometric distortion.
11
+ *
12
+ * This common mapping is included in every channel. Red/blue CA terms are
13
+ * added to this base, so callers should not apply a second distortion pass.
14
+ */
15
+ baseDistortionCoefficients: RadialDistortionCoefficients;
16
+ /** Additional red-channel radial coefficients relative to green. */
17
+ redCoefficientOffset: RadialDistortionCoefficients;
18
+ /** Additional blue-channel radial coefficients relative to green. */
19
+ blueCoefficientOffset: RadialDistortionCoefficients;
20
+ }
21
+ export interface CalculateLateralChromaticAberrationMappingInput {
22
+ /** Ideal/undistorted image-plane point shared by all channels. */
23
+ imagePointMm: LensFieldPointMm;
24
+ profile: LateralChromaticAberrationProfile;
25
+ }
26
+ export interface CalculateInverseLateralChromaticAberrationMappingInput {
27
+ /**
28
+ * Distorted output image-plane destination. Each output channel is inverse-
29
+ * mapped independently to its ideal source coordinate.
30
+ */
31
+ distortedImagePointMm: LensFieldPointMm;
32
+ profile: LateralChromaticAberrationProfile;
33
+ }
34
+ export interface CalculateInverseLateralChromaticAberrationMappingsInput {
35
+ /**
36
+ * Distorted output image-plane destinations. Each destination is inverse-
37
+ * mapped independently for red, green, and blue after one profile-resolution
38
+ * step for the batch.
39
+ */
40
+ distortedImagePointsMm: readonly LensFieldPointMm[];
41
+ profile: LateralChromaticAberrationProfile;
42
+ }
43
+ export interface LateralChromaticAberrationChannelMapping {
44
+ mappedImagePointMm: LensFieldPointMm;
45
+ radialScale: number;
46
+ combinedCoefficients: RadialDistortionCoefficients;
47
+ }
48
+ export interface InverseLateralChromaticAberrationChannelMapping {
49
+ sourceImagePointMm: LensFieldPointMm;
50
+ radialScaleAtSource: number;
51
+ combinedCoefficients: RadialDistortionCoefficients;
52
+ }
53
+ export interface ChannelSeparationVectorMm {
54
+ x: number;
55
+ y: number;
56
+ distance: number;
57
+ }
58
+ export interface LateralChromaticAberrationSeparation {
59
+ redGreen: ChannelSeparationVectorMm;
60
+ blueGreen: ChannelSeparationVectorMm;
61
+ redBlue: ChannelSeparationVectorMm;
62
+ maximumPairDistanceMm: number;
63
+ }
64
+ export interface LateralChromaticAberrationMapping {
65
+ direction: "undistorted-to-channel-distorted";
66
+ referenceChannel: "green";
67
+ sourceImagePointMm: LensFieldPointMm;
68
+ channels: {
69
+ red: LateralChromaticAberrationChannelMapping;
70
+ green: LateralChromaticAberrationChannelMapping;
71
+ blue: LateralChromaticAberrationChannelMapping;
72
+ };
73
+ separation: LateralChromaticAberrationSeparation;
74
+ }
75
+ export interface InverseLateralChromaticAberrationMapping {
76
+ direction: "distorted-output-to-channel-sources";
77
+ referenceChannel: "green";
78
+ distortedImagePointMm: LensFieldPointMm;
79
+ channels: {
80
+ red: InverseLateralChromaticAberrationChannelMapping;
81
+ green: InverseLateralChromaticAberrationChannelMapping;
82
+ blue: InverseLateralChromaticAberrationChannelMapping;
83
+ };
84
+ sourceSeparation: LateralChromaticAberrationSeparation;
85
+ }
86
+ export interface InverseLateralChromaticAberrationMappings {
87
+ direction: "distorted-output-to-channel-sources-batch";
88
+ referenceChannel: "green";
89
+ mappings: readonly InverseLateralChromaticAberrationMapping[];
90
+ pointCount: number;
91
+ }
92
+ /**
93
+ * Calculates generic lateral chromatic-aberration field separation by mapping
94
+ * one ideal image-plane point through a shared green-reference base distortion
95
+ * and red/blue radial coefficient offsets.
96
+ *
97
+ * This is channel-dependent field mapping, not a blur kernel.
98
+ */
99
+ export declare function calculateLateralChromaticAberrationMapping(input: CalculateLateralChromaticAberrationMappingInput): CalculationResult<LateralChromaticAberrationMapping>;
100
+ /**
101
+ * Inverse-maps one distorted output destination independently for the
102
+ * representative red/green/blue channels.
103
+ *
104
+ * Renderers can use the returned per-channel ideal source coordinates for
105
+ * inverse sampling without inventing chromatic-aberration equations.
106
+ */
107
+ export declare function calculateInverseLateralChromaticAberrationMapping(input: CalculateInverseLateralChromaticAberrationMappingInput): CalculationResult<InverseLateralChromaticAberrationMapping>;
108
+ /**
109
+ * Inverse-maps multiple distorted destinations while resolving the shared CA
110
+ * profile once and validating each combined channel profile once for the
111
+ * complete batch.
112
+ *
113
+ * Per-point values match calculateInverseLateralChromaticAberrationMapping();
114
+ * provenance is shared once at the batch boundary.
115
+ */
116
+ export declare function calculateInverseLateralChromaticAberrationMappings(input: CalculateInverseLateralChromaticAberrationMappingsInput): CalculationResult<InverseLateralChromaticAberrationMappings>;
117
+ //# sourceMappingURL=lateral-chromatic-aberration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lateral-chromatic-aberration.d.ts","sourceRoot":"","sources":["../../src/optics/lateral-chromatic-aberration.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,228 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { approximationResult } from "../core/calculation-result.js";
3
+ import { InvalidScientificInputError } from "../core/validation.js";
4
+ import { calculateInverseRadialDistortionMapping, calculateInverseRadialSourcePointValue, calculateRadialDistortionMapping, validateRadialDistortionProfile } from "./radial-distortion.js";
5
+ function requireFiniteCoefficients(path, coefficients) {
6
+ for (const key of ["k1", "k2", "k3"]) {
7
+ if (!Number.isFinite(coefficients[key])) {
8
+ throw new InvalidScientificInputError(`${path}.${key} must be finite.`);
9
+ }
10
+ }
11
+ }
12
+ function addCoefficients(base, offset) {
13
+ return {
14
+ k1: base.k1 + offset.k1,
15
+ k2: base.k2 + offset.k2,
16
+ k3: base.k3 + offset.k3
17
+ };
18
+ }
19
+ function resolveProfiles(profile) {
20
+ requireFiniteCoefficients("profile.baseDistortionCoefficients", profile.baseDistortionCoefficients);
21
+ requireFiniteCoefficients("profile.redCoefficientOffset", profile.redCoefficientOffset);
22
+ requireFiniteCoefficients("profile.blueCoefficientOffset", profile.blueCoefficientOffset);
23
+ const shared = {
24
+ normalizationRadiusMm: profile.normalizationRadiusMm,
25
+ maximumNormalizedRadius: profile.maximumNormalizedRadius
26
+ };
27
+ return {
28
+ red: {
29
+ ...shared,
30
+ coefficients: addCoefficients(profile.baseDistortionCoefficients, profile.redCoefficientOffset)
31
+ },
32
+ green: {
33
+ ...shared,
34
+ coefficients: { ...profile.baseDistortionCoefficients }
35
+ },
36
+ blue: {
37
+ ...shared,
38
+ coefficients: addCoefficients(profile.baseDistortionCoefficients, profile.blueCoefficientOffset)
39
+ }
40
+ };
41
+ }
42
+ function withChannelContext(channel, calculate) {
43
+ try {
44
+ return calculate();
45
+ }
46
+ catch (error) {
47
+ if (error instanceof InvalidScientificInputError) {
48
+ throw new InvalidScientificInputError(`Lateral chromatic aberration ${channel} channel: ${error.message}`);
49
+ }
50
+ throw error;
51
+ }
52
+ }
53
+ function separationVector(first, second) {
54
+ const x = first.x - second.x;
55
+ const y = first.y - second.y;
56
+ return {
57
+ x,
58
+ y,
59
+ distance: Math.hypot(x, y)
60
+ };
61
+ }
62
+ function separations(red, green, blue) {
63
+ const redGreen = separationVector(red, green);
64
+ const blueGreen = separationVector(blue, green);
65
+ const redBlue = separationVector(red, blue);
66
+ return {
67
+ redGreen,
68
+ blueGreen,
69
+ redBlue,
70
+ maximumPairDistanceMm: Math.max(redGreen.distance, blueGreen.distance, redBlue.distance)
71
+ };
72
+ }
73
+ function assumptions() {
74
+ return [
75
+ "Generic lateral chromatic aberration is represented as independent radial field mapping for abstract red, green, and blue renderer channels",
76
+ "Green is the reference field mapping; red and blue coefficient offsets are added to the green-reference base distortion rather than applied as a second warp",
77
+ "All channel mappings share one physical normalization radius and declared operating envelope",
78
+ "Each combined channel radial profile must remain one-to-one over the declared operating envelope",
79
+ "The RGB channel labels are representative rendering channels, not calibrated wavelengths, sensor spectral responses, or CFA primaries",
80
+ "This model changes channel field coordinates only; it does not blur, change PSF shape, modify channel intensity, or model longitudinal chromatic aberration",
81
+ "Profiles are generic caller inputs and do not represent a named lens unless separately calibrated with defensible provenance"
82
+ ];
83
+ }
84
+ /**
85
+ * Calculates generic lateral chromatic-aberration field separation by mapping
86
+ * one ideal image-plane point through a shared green-reference base distortion
87
+ * and red/blue radial coefficient offsets.
88
+ *
89
+ * This is channel-dependent field mapping, not a blur kernel.
90
+ */
91
+ export function calculateLateralChromaticAberrationMapping(input) {
92
+ const profiles = resolveProfiles(input.profile);
93
+ const red = withChannelContext("red", () => calculateRadialDistortionMapping({
94
+ imagePointMm: input.imagePointMm,
95
+ profile: profiles.red
96
+ })).value;
97
+ const green = withChannelContext("green", () => calculateRadialDistortionMapping({
98
+ imagePointMm: input.imagePointMm,
99
+ profile: profiles.green
100
+ })).value;
101
+ const blue = withChannelContext("blue", () => calculateRadialDistortionMapping({
102
+ imagePointMm: input.imagePointMm,
103
+ profile: profiles.blue
104
+ })).value;
105
+ return approximationResult({
106
+ direction: "undistorted-to-channel-distorted",
107
+ referenceChannel: "green",
108
+ sourceImagePointMm: { ...input.imagePointMm },
109
+ channels: {
110
+ red: {
111
+ mappedImagePointMm: { ...red.mappedImagePointMm },
112
+ radialScale: red.radialScale,
113
+ combinedCoefficients: { ...profiles.red.coefficients }
114
+ },
115
+ green: {
116
+ mappedImagePointMm: { ...green.mappedImagePointMm },
117
+ radialScale: green.radialScale,
118
+ combinedCoefficients: { ...profiles.green.coefficients }
119
+ },
120
+ blue: {
121
+ mappedImagePointMm: { ...blue.mappedImagePointMm },
122
+ radialScale: blue.radialScale,
123
+ combinedCoefficients: { ...profiles.blue.coefficients }
124
+ }
125
+ },
126
+ separation: separations(red.mappedImagePointMm, green.mappedImagePointMm, blue.mappedImagePointMm)
127
+ }, "generic-green-reference-lateral-chromatic-aberration", "1.0.0", assumptions());
128
+ }
129
+ /**
130
+ * Inverse-maps one distorted output destination independently for the
131
+ * representative red/green/blue channels.
132
+ *
133
+ * Renderers can use the returned per-channel ideal source coordinates for
134
+ * inverse sampling without inventing chromatic-aberration equations.
135
+ */
136
+ export function calculateInverseLateralChromaticAberrationMapping(input) {
137
+ const profiles = resolveProfiles(input.profile);
138
+ const red = withChannelContext("red", () => calculateInverseRadialDistortionMapping({
139
+ distortedImagePointMm: input.distortedImagePointMm,
140
+ profile: profiles.red
141
+ })).value;
142
+ const green = withChannelContext("green", () => calculateInverseRadialDistortionMapping({
143
+ distortedImagePointMm: input.distortedImagePointMm,
144
+ profile: profiles.green
145
+ })).value;
146
+ const blue = withChannelContext("blue", () => calculateInverseRadialDistortionMapping({
147
+ distortedImagePointMm: input.distortedImagePointMm,
148
+ profile: profiles.blue
149
+ })).value;
150
+ return approximationResult({
151
+ direction: "distorted-output-to-channel-sources",
152
+ referenceChannel: "green",
153
+ distortedImagePointMm: { ...input.distortedImagePointMm },
154
+ channels: {
155
+ red: {
156
+ sourceImagePointMm: { ...red.sourceImagePointMm },
157
+ radialScaleAtSource: red.radialScaleAtSource,
158
+ combinedCoefficients: { ...profiles.red.coefficients }
159
+ },
160
+ green: {
161
+ sourceImagePointMm: { ...green.sourceImagePointMm },
162
+ radialScaleAtSource: green.radialScaleAtSource,
163
+ combinedCoefficients: { ...profiles.green.coefficients }
164
+ },
165
+ blue: {
166
+ sourceImagePointMm: { ...blue.sourceImagePointMm },
167
+ radialScaleAtSource: blue.radialScaleAtSource,
168
+ combinedCoefficients: { ...profiles.blue.coefficients }
169
+ }
170
+ },
171
+ sourceSeparation: separations(red.sourceImagePointMm, green.sourceImagePointMm, blue.sourceImagePointMm)
172
+ }, "generic-inverse-green-reference-lateral-chromatic-aberration", "1.0.0", assumptions());
173
+ }
174
+ /**
175
+ * Inverse-maps multiple distorted destinations while resolving the shared CA
176
+ * profile once and validating each combined channel profile once for the
177
+ * complete batch.
178
+ *
179
+ * Per-point values match calculateInverseLateralChromaticAberrationMapping();
180
+ * provenance is shared once at the batch boundary.
181
+ */
182
+ export function calculateInverseLateralChromaticAberrationMappings(input) {
183
+ const profiles = resolveProfiles(input.profile);
184
+ const validatedProfiles = {
185
+ red: withChannelContext("red", () => validateRadialDistortionProfile(profiles.red)),
186
+ green: withChannelContext("green", () => validateRadialDistortionProfile(profiles.green)),
187
+ blue: withChannelContext("blue", () => validateRadialDistortionProfile(profiles.blue))
188
+ };
189
+ const mappings = input.distortedImagePointsMm.map((point, index) => {
190
+ const red = withChannelContext("red", () => calculateInverseRadialSourcePointValue(point, validatedProfiles.red, `distortedImagePointsMm[${index}]`));
191
+ const green = withChannelContext("green", () => calculateInverseRadialSourcePointValue(point, validatedProfiles.green, `distortedImagePointsMm[${index}]`));
192
+ const blue = withChannelContext("blue", () => calculateInverseRadialSourcePointValue(point, validatedProfiles.blue, `distortedImagePointsMm[${index}]`));
193
+ return {
194
+ direction: "distorted-output-to-channel-sources",
195
+ referenceChannel: "green",
196
+ distortedImagePointMm: { ...point },
197
+ channels: {
198
+ red: {
199
+ sourceImagePointMm: { ...red.sourceImagePointMm },
200
+ radialScaleAtSource: red.radialScaleAtSource,
201
+ combinedCoefficients: { ...profiles.red.coefficients }
202
+ },
203
+ green: {
204
+ sourceImagePointMm: { ...green.sourceImagePointMm },
205
+ radialScaleAtSource: green.radialScaleAtSource,
206
+ combinedCoefficients: { ...profiles.green.coefficients }
207
+ },
208
+ blue: {
209
+ sourceImagePointMm: { ...blue.sourceImagePointMm },
210
+ radialScaleAtSource: blue.radialScaleAtSource,
211
+ combinedCoefficients: { ...profiles.blue.coefficients }
212
+ }
213
+ },
214
+ sourceSeparation: separations(red.sourceImagePointMm, green.sourceImagePointMm, blue.sourceImagePointMm)
215
+ };
216
+ });
217
+ return approximationResult({
218
+ direction: "distorted-output-to-channel-sources-batch",
219
+ referenceChannel: "green",
220
+ mappings,
221
+ pointCount: mappings.length
222
+ }, "generic-inverse-green-reference-lateral-chromatic-aberration-batch", "1.0.0", [
223
+ ...assumptions(),
224
+ "Combined red/green/blue radial profiles are resolved once for the batch",
225
+ "Each channel profile is validated once before batch point sampling"
226
+ ]);
227
+ }
228
+ //# sourceMappingURL=lateral-chromatic-aberration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lateral-chromatic-aberration.js","sourceRoot":"","sources":["../../src/optics/lateral-chromatic-aberration.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ import { type CalculationProvenance, type CalculationResult } from "../core/calculation-result.js";
2
+ import type { LensFieldPointMm } from "./radial-distortion.js";
3
+ export declare const PSF_FOUNDATION_VERSION: "0.1.0";
4
+ export type PsfContributionId = "geometric-defocus-circle" | "circular-diffraction-first-zero" | "non-circular-diffraction" | "mechanical-pupil-clipping" | "field-curvature" | "field-dependent-aberration" | "field-dependent-bokeh";
5
+ export type PsfContributionStatus = "implemented-diagnostic" | "reserved-contract";
6
+ export interface PsfContributionContract {
7
+ id: PsfContributionId;
8
+ status: PsfContributionStatus;
9
+ dependsOn: readonly ("field-position" | "focus-depth" | "pupil" | "wavelength")[];
10
+ note: string;
11
+ }
12
+ export interface PsfFoundationContract {
13
+ version: typeof PSF_FOUNDATION_VERSION;
14
+ coordinateSpace: "image-plane-metric";
15
+ fieldAxes: "+X right, +Y up";
16
+ compositionPolicy: "separate-contributions-no-combined-psf";
17
+ contributions: readonly PsfContributionContract[];
18
+ previewReferencePolicy: {
19
+ previewMayApproximate: true;
20
+ referenceMayUseHigherFidelity: true;
21
+ mustPreserveContributionSemantics: true;
22
+ };
23
+ notes: readonly string[];
24
+ }
25
+ export interface CalculatePsfFoundationComponentsInput {
26
+ focalLengthMm: number;
27
+ aperture: number;
28
+ focusDistanceM: number;
29
+ subjectDistanceM: number;
30
+ /**
31
+ * Image-plane field position relative to the optical axis, in millimetres.
32
+ * +X is right and +Y is up.
33
+ */
34
+ fieldPointMm: LensFieldPointMm;
35
+ /**
36
+ * Physical image-plane radius used only to normalize field position for
37
+ * cross-case diagnostics. It is not a lens calibration or validity bound.
38
+ */
39
+ fieldNormalizationRadiusMm: number;
40
+ spectralBasis: {
41
+ kind: "monochromatic";
42
+ wavelengthNm: number;
43
+ };
44
+ }
45
+ export interface PsfFoundationComponents {
46
+ context: {
47
+ field: {
48
+ imagePointMm: LensFieldPointMm;
49
+ radiusMm: number;
50
+ normalizationRadiusMm: number;
51
+ normalizedRadius: number;
52
+ };
53
+ depth: {
54
+ focusDistanceM: number;
55
+ subjectDistanceM: number;
56
+ };
57
+ spectralBasis: {
58
+ kind: "monochromatic";
59
+ wavelengthNm: number;
60
+ };
61
+ pupil: {
62
+ kind: "ideal-circular-f-number-derived";
63
+ apertureFNumber: number;
64
+ diameterMm: number;
65
+ };
66
+ };
67
+ contributions: {
68
+ geometricDefocus: {
69
+ id: "geometric-defocus-circle";
70
+ diameterMm: number;
71
+ provenance: CalculationProvenance;
72
+ };
73
+ circularDiffraction: {
74
+ id: "circular-diffraction-first-zero";
75
+ firstZeroDiameterMicrometers: number;
76
+ provenance: CalculationProvenance;
77
+ };
78
+ };
79
+ composition: {
80
+ status: "not-composed";
81
+ note: string;
82
+ };
83
+ }
84
+ /**
85
+ * Returns the public PSF/pupil foundation contract.
86
+ *
87
+ * The contract describes current diagnostics plus reserved future contribution
88
+ * ownership. It does not imply that reserved contributions are implemented.
89
+ */
90
+ export declare function getPsfFoundationContract(): PsfFoundationContract;
91
+ /**
92
+ * Evaluates the currently implemented PSF-related diagnostics in one explicit
93
+ * field/depth/spectral/pupil context without combining them into a synthetic
94
+ * PSF or blur radius.
95
+ *
96
+ * Field position is recorded even though the current defocus-circle and
97
+ * circular-Airy diagnostics are not field dependent. Future field-dependent
98
+ * contributions can consume the same context without changing these existing
99
+ * primitives.
100
+ */
101
+ export declare function calculatePsfFoundationComponents(input: CalculatePsfFoundationComponentsInput): CalculationResult<PsfFoundationComponents>;
102
+ //# sourceMappingURL=psf-foundation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"psf-foundation.d.ts","sourceRoot":"","sources":["../../src/optics/psf-foundation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,164 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { calculatedResult } from "../core/calculation-result.js";
3
+ import { InvalidScientificInputError, requirePositiveFinite } from "../core/validation.js";
4
+ import { calculateDefocusCircle } from "./depth-of-field.js";
5
+ import { calculateAiryDisk } from "./diffraction.js";
6
+ export const PSF_FOUNDATION_VERSION = "0.1.0";
7
+ const CONTRIBUTIONS = [
8
+ {
9
+ id: "geometric-defocus-circle",
10
+ status: "implemented-diagnostic",
11
+ dependsOn: ["focus-depth", "pupil"],
12
+ note: "Existing thin-lens geometric defocus diameter. This is a blur-circle diagnostic, not a complete intensity PSF."
13
+ },
14
+ {
15
+ id: "circular-diffraction-first-zero",
16
+ status: "implemented-diagnostic",
17
+ dependsOn: ["pupil", "wavelength"],
18
+ note: "Existing ideal circular-pupil first-zero Airy diameter. This is a diffraction-size diagnostic, not a sampled intensity PSF."
19
+ },
20
+ {
21
+ id: "non-circular-diffraction",
22
+ status: "reserved-contract",
23
+ dependsOn: ["pupil", "wavelength", "field-position"],
24
+ note: "Reserved for a defensible pupil-dependent diffraction model. Polygon aperture geometry alone does not implement this contribution."
25
+ },
26
+ {
27
+ id: "mechanical-pupil-clipping",
28
+ status: "reserved-contract",
29
+ dependsOn: ["pupil", "field-position"],
30
+ note: "Reserved for field-dependent pupil clipping/mechanical vignetting that can affect both throughput and PSF/bokeh shape."
31
+ },
32
+ {
33
+ id: "field-curvature",
34
+ status: "reserved-contract",
35
+ dependsOn: ["field-position", "focus-depth"],
36
+ note: "Reserved for field-dependent focus displacement. It must not be represented as geometric distortion."
37
+ },
38
+ {
39
+ id: "field-dependent-aberration",
40
+ status: "reserved-contract",
41
+ dependsOn: ["field-position", "focus-depth", "pupil", "wavelength"],
42
+ note: "Reserved for defensible field-dependent aberration/PSF structure. Do not replace this with a generic lens-sharpness score."
43
+ },
44
+ {
45
+ id: "field-dependent-bokeh",
46
+ status: "reserved-contract",
47
+ dependsOn: ["field-position", "focus-depth", "pupil"],
48
+ note: "Reserved for field-dependent out-of-focus PSF/bokeh behavior, including future cat's-eye effects when pupil clipping is modeled."
49
+ }
50
+ ];
51
+ const NOTES = [
52
+ "This foundation preserves PSF-related contributions separately; it does not calculate a combined PSF, MTF, or one scalar lens-sharpness result.",
53
+ "Existing geometric defocus and circular Airy outputs remain independently named scientific diagnostics with their own provenance.",
54
+ "Reserved contributions describe ownership/dependencies only and do not claim implemented visual behavior.",
55
+ "Illumination vignetting is a separate throughput-only model and is not a PSF contribution.",
56
+ "Real-lens PSF calibration requires defensible provenance, compatible reuse rights, and explicit limitations/uncertainty."
57
+ ];
58
+ /**
59
+ * Returns the public PSF/pupil foundation contract.
60
+ *
61
+ * The contract describes current diagnostics plus reserved future contribution
62
+ * ownership. It does not imply that reserved contributions are implemented.
63
+ */
64
+ export function getPsfFoundationContract() {
65
+ return {
66
+ version: PSF_FOUNDATION_VERSION,
67
+ coordinateSpace: "image-plane-metric",
68
+ fieldAxes: "+X right, +Y up",
69
+ compositionPolicy: "separate-contributions-no-combined-psf",
70
+ contributions: CONTRIBUTIONS.map((contribution) => ({
71
+ ...contribution,
72
+ dependsOn: [...contribution.dependsOn]
73
+ })),
74
+ previewReferencePolicy: {
75
+ previewMayApproximate: true,
76
+ referenceMayUseHigherFidelity: true,
77
+ mustPreserveContributionSemantics: true
78
+ },
79
+ notes: [...NOTES]
80
+ };
81
+ }
82
+ /**
83
+ * Evaluates the currently implemented PSF-related diagnostics in one explicit
84
+ * field/depth/spectral/pupil context without combining them into a synthetic
85
+ * PSF or blur radius.
86
+ *
87
+ * Field position is recorded even though the current defocus-circle and
88
+ * circular-Airy diagnostics are not field dependent. Future field-dependent
89
+ * contributions can consume the same context without changing these existing
90
+ * primitives.
91
+ */
92
+ export function calculatePsfFoundationComponents(input) {
93
+ requirePositiveFinite("focalLengthMm", input.focalLengthMm);
94
+ requirePositiveFinite("aperture", input.aperture);
95
+ requirePositiveFinite("focusDistanceM", input.focusDistanceM);
96
+ requirePositiveFinite("subjectDistanceM", input.subjectDistanceM);
97
+ requirePositiveFinite("fieldNormalizationRadiusMm", input.fieldNormalizationRadiusMm);
98
+ if (input.spectralBasis?.kind !== "monochromatic") {
99
+ throw new InvalidScientificInputError('spectralBasis.kind must be "monochromatic".');
100
+ }
101
+ requirePositiveFinite("spectralBasis.wavelengthNm", input.spectralBasis.wavelengthNm);
102
+ if (!Number.isFinite(input.fieldPointMm.x)) {
103
+ throw new InvalidScientificInputError("fieldPointMm.x must be finite.");
104
+ }
105
+ if (!Number.isFinite(input.fieldPointMm.y)) {
106
+ throw new InvalidScientificInputError("fieldPointMm.y must be finite.");
107
+ }
108
+ const defocus = calculateDefocusCircle({
109
+ focalLengthMm: input.focalLengthMm,
110
+ aperture: input.aperture,
111
+ focusDistanceM: input.focusDistanceM,
112
+ subjectDistanceM: input.subjectDistanceM
113
+ });
114
+ const diffraction = calculateAiryDisk({
115
+ aperture: input.aperture,
116
+ wavelengthNm: input.spectralBasis.wavelengthNm
117
+ });
118
+ const radiusMm = Math.hypot(input.fieldPointMm.x, input.fieldPointMm.y);
119
+ return calculatedResult({
120
+ context: {
121
+ field: {
122
+ imagePointMm: { ...input.fieldPointMm },
123
+ radiusMm,
124
+ normalizationRadiusMm: input.fieldNormalizationRadiusMm,
125
+ normalizedRadius: radiusMm / input.fieldNormalizationRadiusMm
126
+ },
127
+ depth: {
128
+ focusDistanceM: input.focusDistanceM,
129
+ subjectDistanceM: input.subjectDistanceM
130
+ },
131
+ spectralBasis: {
132
+ kind: "monochromatic",
133
+ wavelengthNm: input.spectralBasis.wavelengthNm
134
+ },
135
+ pupil: {
136
+ kind: "ideal-circular-f-number-derived",
137
+ apertureFNumber: input.aperture,
138
+ diameterMm: input.focalLengthMm / input.aperture
139
+ }
140
+ },
141
+ contributions: {
142
+ geometricDefocus: {
143
+ id: "geometric-defocus-circle",
144
+ diameterMm: defocus.value.diameterMm,
145
+ provenance: { ...defocus.provenance }
146
+ },
147
+ circularDiffraction: {
148
+ id: "circular-diffraction-first-zero",
149
+ firstZeroDiameterMicrometers: diffraction.value.firstZeroDiameterMicrometers,
150
+ provenance: { ...diffraction.provenance }
151
+ }
152
+ },
153
+ composition: {
154
+ status: "not-composed",
155
+ note: "No combined PSF, MTF, convolution kernel, or scalar sharpness value has been calculated."
156
+ }
157
+ }, "psf-foundation-separated-components", "1.0.0", [
158
+ "Current geometric defocus and ideal circular-pupil diffraction diagnostics are evaluated independently",
159
+ "Field position is explicit context but does not alter the current field-invariant diagnostic primitives",
160
+ "The result intentionally does not combine defocus and diffraction into one blur radius or PSF",
161
+ "Illumination vignetting is excluded because it is a separate throughput-only stage"
162
+ ]);
163
+ }
164
+ //# sourceMappingURL=psf-foundation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"psf-foundation.js","sourceRoot":"","sources":["../../src/optics/psf-foundation.ts"],"names":[],"mappings":"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"}