@photivra/engine 2.14.0 → 2.15.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 +30 -1
- package/CITATION.cff +1 -1
- package/NOTICE +5 -4
- package/README.md +9 -7
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +15 -11
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +1 -1
- package/dist/facade/simulate-capture.js +15 -4
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/optics/defocus-disc-kernel.d.ts +90 -1
- package/dist/optics/defocus-disc-kernel.js +58 -5
- package/dist/optics/defocus-disc-kernel.js.map +1 -1
- package/dist/optics/diffraction-psf-profile.d.ts +9 -4
- package/dist/optics/diffraction-psf-profile.js +14 -6
- package/dist/optics/diffraction-psf-profile.js.map +1 -1
- package/dist/optics/lens-psf-kernels.d.ts +13 -2
- package/dist/optics/lens-psf-kernels.js +23 -6
- package/dist/optics/lens-psf-kernels.js.map +1 -1
- package/dist/optics/site-diffraction-kernel.d.ts +1 -1
- package/dist/optics/site-diffraction-kernel.js +37 -17
- package/dist/optics/site-diffraction-kernel.js.map +1 -1
- package/dist/output/print-contrast-reference.js +2 -2
- package/dist/output/print-contrast-reference.js.map +1 -1
- package/docs/AGENT_GUIDE.md +1 -0
- package/docs/API_REFERENCE.md +12 -1
- package/docs/QUICK_START.md +20 -4
- package/docs/USAGE.md +17 -0
- package/docs/api/core-version.md +1 -1
- package/docs/api/exports.json +22 -2
- package/docs/api/facade-simulate-capture.md +1 -1
- package/docs/api/optics-defocus-disc-kernel.md +86 -0
- package/docs/api/optics-diffraction-psf-profile.md +6 -3
- package/docs/api/optics-lens-psf-kernels.md +3 -2
- package/llms.txt +1 -0
- package/package.json +1 -1
|
@@ -853,7 +853,7 @@ export interface SimulateDisplayViewOptions {
|
|
|
853
853
|
/** Display pixels, 1 to the capture's output width and height. */
|
|
854
854
|
width: number;
|
|
855
855
|
height: number;
|
|
856
|
-
/** Stratified Monte Carlo samples per axis for each display pixel's expected value (1–32, default
|
|
856
|
+
/** Stratified Monte Carlo samples per axis for each display pixel's expected value (1–32, default 16: 256 real pixels where the display pixel has detail). */
|
|
857
857
|
samplesPerAxis?: number;
|
|
858
858
|
/** "srgb-8" (default) or "srgb-16". */
|
|
859
859
|
format?: "srgb-8" | "srgb-16";
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# optics/defocus-disc-kernel.ts public contracts
|
|
2
|
+
|
|
3
|
+
The package and root API versions are recorded once in [Navigation](../API_REFERENCE.md) · [Developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Generated signatures retain independent schema/model versions. Only the exports listed here are root-package contracts; module-local helpers are not supported deep imports.
|
|
4
|
+
|
|
5
|
+
## calculateDefocusDiscKernelRadius
|
|
6
|
+
|
|
7
|
+
Checks, before rendering, whether `lens.defocus: { model: "geometric-disc" }` can render a request: the geometric
|
|
8
|
+
defocus disc's diameter on the site lattice, the kernel radius it needs, and whether that radius is within
|
|
9
|
+
{@link DEFOCUS_DISC_KERNEL_MAXIMUM_RADIUS_SITES} (#532). Pure and cheap: no kernel is built and nothing is rendered.
|
|
10
|
+
|
|
11
|
+
It runs the same resolution and the same limit test as `simulateCapture`, `simulateDisplayView` and `prepareDisplayView`
|
|
12
|
+
(the blur circle c = f²·|s − d| / (N·d·(s − f)) of `calculateDefocusCircle`, thin-lens model 1.1.0, divided by the pitch),
|
|
13
|
+
so for the same focal length, f-number, distances and pitch a request they refuse for its defocus size has
|
|
14
|
+
`withinLimit: false`, and one they accept has `withinLimit: true`. Pass the values the capture uses: in an automatic
|
|
15
|
+
exposure mode that is the resolved f-number. The limit applies to the disc alone; with `lens.diffraction` the combined
|
|
16
|
+
kernel (diffraction radius plus defocus radius, at most 32 + 64 sites) has no further limit. Other reasons a capture
|
|
17
|
+
refuses `lens.defocus` out of focus (camera rotation, projection, distortion, vignetting, pupil sampling, a caller PSF)
|
|
18
|
+
are not checked here.
|
|
19
|
+
|
|
20
|
+
The blur circle is a geometric thin-lens approximation for an ideal uniform circular pupil (no diffraction, aberrations
|
|
21
|
+
or pupil vignetting). Inputs follow `calculateDefocusCircle`: all positive and finite, both distances beyond the focal
|
|
22
|
+
length; invalid values fail with `InvalidScientificInputError`, unknown fields with `InvalidConfigurationError`.
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
export function calculateDefocusDiscKernelRadius(input: CalculateDefocusDiscKernelRadiusInput): CalculationResult<DefocusDiscKernelRadius>;
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This call is synchronous; any supplied provider must follow its explicit synchronous contract.
|
|
29
|
+
|
|
30
|
+
## CalculateDefocusDiscKernelRadiusInput
|
|
31
|
+
|
|
32
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
export interface CalculateDefocusDiscKernelRadiusInput {
|
|
36
|
+
/** Lens focal length in millimetres (`lens.focalLengthMm`). */
|
|
37
|
+
focalLengthMm: number;
|
|
38
|
+
/** F-number the capture uses: `lens.fNumber`, or in an automatic exposure mode the resolved `exposure.settings.fNumber`. */
|
|
39
|
+
aperture: number;
|
|
40
|
+
/** Focus-plane distance from the lens plane in metres (`lens.focusDistanceM`; `simulateCapture` defaults it to the subject distance). */
|
|
41
|
+
focusDistanceM: number;
|
|
42
|
+
/** Scene-plane distance from the lens plane in metres (`subjectDistanceM`). */
|
|
43
|
+
subjectDistanceM: number;
|
|
44
|
+
/** Sensor site pitch in micrometres (`sensor.pixelPitchMicrometers`), the lattice the disc is sampled on. */
|
|
45
|
+
pixelPitchMicrometers: number;
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## DEFOCUS_DISC_KERNEL_MAXIMUM_RADIUS_SITES
|
|
50
|
+
|
|
51
|
+
Largest kernel radius in sites of `lens.defocus: { model: "geometric-disc" }`, R ≤ 64: a disc of at most 129 sites
|
|
52
|
+
across (a 129 × 129 window, 16 641 taps per site; the diffraction kernels stop at 32). `simulateCapture`,
|
|
53
|
+
`simulateDisplayView` and `prepareDisplayView` refuse a request whose disc needs more, and never clip the disc; check a
|
|
54
|
+
request first with {@link calculateDefocusDiscKernelRadius}.
|
|
55
|
+
|
|
56
|
+
Set from the cost measured in the capture (#492, step 2a; docs/QUICK_START.md, "Optics"): the capture's time grows with
|
|
57
|
+
R² at every site the disc sees an edge from, and a 0.7 MP Siemens star took 0.37 s in focus, 2.9 s at R = 32, 4.7 s at
|
|
58
|
+
R = 41 and 11.6 s at R = 64 (Node, one thread). 64 keeps the issue's 1.4 µm example (50 mm f/2.8, subject 2 m, focus
|
|
59
|
+
1.6 m: R = 41) with room for larger blurs, at a cost the caller chooses and the docs state; past it the call fails.
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
DEFOCUS_DISC_KERNEL_MAXIMUM_RADIUS_SITES = 64
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## DefocusDiscKernelRadius
|
|
66
|
+
|
|
67
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
export interface DefocusDiscKernelRadius {
|
|
71
|
+
/** Geometric blur-circle diameter c at the sensor in micrometres (`calculateDefocusCircle`, thin-lens model 1.1.0); 0 in focus. */
|
|
72
|
+
diameterMicrometers: number;
|
|
73
|
+
/** c / pixel pitch: the disc's diameter in sites. */
|
|
74
|
+
diameterSites: number;
|
|
75
|
+
/** Kernel radius R in sites the renderer needs for this disc, ⌈c / (2·pitch) − ½⌉ (0 for a disc inside one site, and in focus). */
|
|
76
|
+
kernelRadiusSites: number;
|
|
77
|
+
/** {@link DEFOCUS_DISC_KERNEL_MAXIMUM_RADIUS_SITES}, 64. */
|
|
78
|
+
maximumKernelRadiusSites: number;
|
|
79
|
+
/** Largest disc diameter in sites within the limit, 2·64 + 1 = 129: within the limit exactly when `diameterSites` ≤ 129. */
|
|
80
|
+
maximumDiameterSites: number;
|
|
81
|
+
/** True when `kernelRadiusSites` ≤ `maximumKernelRadiusSites`: `lens.defocus` renders the request; false: it refuses it. */
|
|
82
|
+
withinLimit: boolean;
|
|
83
|
+
/** How far past the limit the kernel radius is, max(0, R − 64) sites; 0 when within the limit. */
|
|
84
|
+
excessKernelRadiusSites: number;
|
|
85
|
+
}
|
|
86
|
+
```
|
|
@@ -26,7 +26,7 @@ export interface CreateDiffractionLimitedPsfProfileInput {
|
|
|
26
26
|
focalLengthMm: number;
|
|
27
27
|
apertureFNumber: number;
|
|
28
28
|
focus: FocusPlane;
|
|
29
|
-
/** Strictly increasing wavelengths, nm, in the medium of propagation (no air/vacuum conversion is applied). 1–
|
|
29
|
+
/** Strictly increasing wavelengths, nm, in the medium of propagation (no air/vacuum conversion is applied). 1–400. */
|
|
30
30
|
wavelengthsNm: readonly number[];
|
|
31
31
|
/** Square sample pitch of every kernel, µm. */
|
|
32
32
|
samplePitchMicrometers: number;
|
|
@@ -40,10 +40,13 @@ export interface CreateDiffractionLimitedPsfProfileInput {
|
|
|
40
40
|
|
|
41
41
|
## DIFFRACTION_LIMITED_PSF_PROFILE_LIMITS
|
|
42
42
|
|
|
43
|
-
Input limits: at most
|
|
43
|
+
Input limits: at most 400 wavelengths, kernel radius 0–32 samples (the irradiance-convolution limit). 400 is the finest spectral
|
|
44
|
+
sampling of `simulateCapture` and the display view (`sensor.spectralStepNanometers` 1 nm over 380–780 nm), so `lens.diffraction`
|
|
45
|
+
builds one exact kernel per spectral node at every allowed step; it was 64 before 2.15.0, which refused every step under 6.25 nm.
|
|
46
|
+
The work and memory are linear in the count (measured in docs/PSF_FOUNDATION.md, "Spectral nodes").
|
|
44
47
|
|
|
45
48
|
```ts
|
|
46
|
-
DIFFRACTION_LIMITED_PSF_PROFILE_LIMITS = Object.freeze({ maximumWavelengths:
|
|
49
|
+
DIFFRACTION_LIMITED_PSF_PROFILE_LIMITS = Object.freeze({ maximumWavelengths: 400, maximumKernelRadiusSamples: 32 })
|
|
47
50
|
```
|
|
48
51
|
|
|
49
52
|
## DIFFRACTION_LIMITED_PSF_PROFILE_MODEL
|
|
@@ -4,10 +4,11 @@ The package and root API versions are recorded once in [Navigation](../API_REFER
|
|
|
4
4
|
|
|
5
5
|
## LENS_PSF_CONVOLUTION_KERNELS_MAXIMUM_WAVELENGTHS
|
|
6
6
|
|
|
7
|
-
At most this many wavelengths per call
|
|
7
|
+
At most this many wavelengths per call: 400, the finest spectral sampling of `simulateCapture` (1 nm over 380–780 nm),
|
|
8
|
+
as `DIFFRACTION_LIMITED_PSF_PROFILE_LIMITS.maximumWavelengths` (64 before 2.15.0). The work is linear in the count.
|
|
8
9
|
|
|
9
10
|
```ts
|
|
10
|
-
LENS_PSF_CONVOLUTION_KERNELS_MAXIMUM_WAVELENGTHS =
|
|
11
|
+
LENS_PSF_CONVOLUTION_KERNELS_MAXIMUM_WAVELENGTHS = 400
|
|
11
12
|
```
|
|
12
13
|
|
|
13
14
|
## LENS_PSF_CONVOLUTION_KERNELS_SCHEMA_VERSION
|
package/llms.txt
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
- [calculateEquivalentIso()](https://github.com/Photivra/photivra/blob/main/docs/api/exposure-exposure.md#calculateequivalentiso): ISO that keeps the same brightness after an aperture or shutter change
|
|
21
21
|
- [calculateDepthOfField()](https://github.com/Photivra/photivra/blob/main/docs/api/optics-depth-of-field.md#calculatedepthoffield): near and far limits and hyperfocal distance (thin lens)
|
|
22
22
|
- [calculateDefocusCircle()](https://github.com/Photivra/photivra/blob/main/docs/api/optics-depth-of-field.md#calculatedefocuscircle): blur-circle size for an out-of-focus subject
|
|
23
|
+
- [calculateDefocusDiscKernelRadius()](https://github.com/Photivra/photivra/blob/main/docs/api/optics-defocus-disc-kernel.md#calculatedefocusdisckernelradius): whether `lens.defocus` can render a blur before you render it (the 64-site limit)
|
|
23
24
|
- [calculateFieldOfView()](https://github.com/Photivra/photivra/blob/main/docs/api/camera-field-of-view.md#calculatefieldofview): angle of view from focal length and sensor size
|
|
24
25
|
- [calculateEquivalentFocalLength35Mm()](https://github.com/Photivra/photivra/blob/main/docs/api/camera-equivalent-focal-length.md#calculateequivalentfocallength35mm): crop factor and 35 mm-equivalent focal length
|
|
25
26
|
- [calculateCenteredCrop()](https://github.com/Photivra/photivra/blob/main/docs/api/output-crop.md#calculatecenteredcrop): pixels left after a centred crop
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@photivra/engine",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.15.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Scientific TypeScript engine for camera optics, exposure, focus, motion, sensor sampling, diffraction, and digital imaging calculations.",
|
|
6
6
|
"type": "module",
|