@photivra/engine 2.9.0 → 2.10.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 (72) hide show
  1. package/CHANGELOG.md +85 -1
  2. package/CITATION.cff +1 -1
  3. package/README.md +6 -6
  4. package/SECURITY.md +1 -1
  5. package/THIRD_PARTY.md +2 -0
  6. package/dist/capture/native-environment-lean.js +89 -5
  7. package/dist/capture/native-environment-lean.js.map +1 -1
  8. package/dist/capture/native-environment-tabulated.d.ts +37 -0
  9. package/dist/capture/native-environment-tabulated.js +42 -6
  10. package/dist/capture/native-environment-tabulated.js.map +1 -1
  11. package/dist/core/portable-math.d.ts +13 -0
  12. package/dist/core/portable-math.js +43 -0
  13. package/dist/core/portable-math.js.map +1 -1
  14. package/dist/core/version.d.ts +1 -1
  15. package/dist/core/version.js +1 -1
  16. package/dist/core/version.js.map +1 -1
  17. package/dist/facade/channel-response.d.ts +15 -0
  18. package/dist/facade/channel-response.js +33 -0
  19. package/dist/facade/channel-response.js.map +1 -0
  20. package/dist/facade/diffraction-provider.js +50 -15
  21. package/dist/facade/diffraction-provider.js.map +1 -1
  22. package/dist/facade/display-view.d.ts +75 -0
  23. package/dist/facade/display-view.js +471 -109
  24. package/dist/facade/display-view.js.map +1 -1
  25. package/dist/facade/expected-signal-setup.js +2 -1
  26. package/dist/facade/expected-signal-setup.js.map +1 -1
  27. package/dist/facade/expected-signal.d.ts +32 -3
  28. package/dist/facade/expected-signal.js +192 -24
  29. package/dist/facade/expected-signal.js.map +1 -1
  30. package/dist/facade/simulate-capture.d.ts +51 -4
  31. package/dist/facade/simulate-capture.js +130 -31
  32. package/dist/facade/simulate-capture.js.map +1 -1
  33. package/dist/facade/simulate-display-view.d.ts +25 -2
  34. package/dist/facade/simulate-display-view.js +55 -22
  35. package/dist/facade/simulate-display-view.js.map +1 -1
  36. package/dist/gpu/image-kernel-execution.d.ts +5 -0
  37. package/dist/gpu/image-kernel-execution.js +2 -2
  38. package/dist/gpu/image-kernel-execution.js.map +1 -1
  39. package/dist/index.d.ts +2 -2
  40. package/dist/index.js +2 -2
  41. package/dist/index.js.map +1 -1
  42. package/dist/optics/irradiance-convolution.d.ts +11 -0
  43. package/dist/optics/irradiance-convolution.js +64 -24
  44. package/dist/optics/irradiance-convolution.js.map +1 -1
  45. package/dist/optics/scene-to-sensor-irradiance.d.ts +13 -0
  46. package/dist/optics/scene-to-sensor-irradiance.js +58 -24
  47. package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
  48. package/dist/optics/sensor-aperture-rays.js +2 -1
  49. package/dist/optics/sensor-aperture-rays.js.map +1 -1
  50. package/dist/optics/sensor-environment-query.js +4 -3
  51. package/dist/optics/sensor-environment-query.js.map +1 -1
  52. package/dist/optics/site-diffraction-kernel.d.ts +16 -0
  53. package/dist/optics/site-diffraction-kernel.js +60 -8
  54. package/dist/optics/site-diffraction-kernel.js.map +1 -1
  55. package/dist/processing/demosaic.js +114 -37
  56. package/dist/processing/demosaic.js.map +1 -1
  57. package/dist/schema/scene-radiance.d.ts +8 -0
  58. package/dist/schema/scene-radiance.js +28 -17
  59. package/dist/schema/scene-radiance.js.map +1 -1
  60. package/dist/sensor/environment-photo-signal.d.ts +21 -0
  61. package/dist/sensor/environment-photo-signal.js +68 -2
  62. package/dist/sensor/environment-photo-signal.js.map +1 -1
  63. package/docs/API_REFERENCE.md +16 -1
  64. package/docs/QUICK_START.md +18 -8
  65. package/docs/USAGE.md +30 -0
  66. package/docs/api/core-version.md +1 -1
  67. package/docs/api/exports.json +42 -2
  68. package/docs/api/facade-display-view.md +50 -0
  69. package/docs/api/facade-simulate-capture.md +60 -8
  70. package/docs/api/facade-simulate-display-view.md +23 -1
  71. package/docs/api/gpu-image-kernel-execution.md +5 -0
  72. package/package.json +1 -1
@@ -30,7 +30,9 @@ export interface DisplayViewResult {
30
30
  * milliseconds (diagnostic only; never affects the samples).
31
31
  */
32
32
  diagnostics: { sampleCount: number; siteEvaluations: number; sceneLookups: number; detailPixelCount: number; uniformPixelCount: number; ahdCorrectedPixelCount: number;
33
- timingsMs: { view: number; total: number } };
33
+ timingsMs: { view: number; total: number };
34
+ /** #395: exact or fast, as requested and as run (see {@link SimulateCaptureFastReport}). */
35
+ fast: SimulateCaptureFastReport };
34
36
  provenance: { scientificStatus: "approximation"; cameraPresetId: string; cameraPresetVersion: string; evidence: readonly EvidenceProvenance[];
35
37
  composedContracts: readonly string[]; limitations: readonly string[] };
36
38
  /** The capture request's assumptions, then `view.definition`, `view.estimation`, `view.noise`, `view.demosaic` and `view.source`. */
@@ -118,6 +120,16 @@ Version of how the facade builds requests. It changes whenever the same input wo
118
120
  SIMULATE_CAPTURE_FACADE_VERSION = "1.0.0" as const
119
121
  ```
120
122
 
123
+ ## SIMULATE_CAPTURE_FAST_OPTIONS
124
+
125
+ The options that take the exact-or-fast flag (#395), in the path style of {@link SIMULATE_CAPTURE_COST_OPTIONS}: each accepts
126
+ the record form with `fast` and is reported in `diagnostics.fast.applied` when it runs. Every one of them takes the flag,
127
+ whether or not it has a fast method yet; one without runs exact and reports `false`.
128
+
129
+ ```ts
130
+ SIMULATE_CAPTURE_FAST_OPTIONS = Object.freeze(["lens.diffraction", "sensor.antiAliasing", "sensor.pixelAperture.box", "output.demosaic.ahd"] as const)
131
+ ```
132
+
121
133
  ## SIMULATE_DISPLAY_VIEW_DEFAULT_SAMPLES_PER_AXIS
122
134
 
123
135
  Default stratified samples per axis of a display view (`view.samplesPerAxis`): 16 × 16 sampled real pixels per display pixel with detail, 4 × 4 where it is uniform.
@@ -193,6 +205,14 @@ edge-directed method that reduces zipper and false colour on sharp edges.
193
205
  export type SimulateCaptureDemosaic = "bilinear" | "ahd";
194
206
  ```
195
207
 
208
+ ## SimulateCaptureDemosaicRecord
209
+
210
+ `output.demosaic` as a record (#395): the demosaic and its `fast` override (see {@link SimulateCaptureOptions.fast}).
211
+
212
+ ```ts
213
+ export interface SimulateCaptureDemosaicRecord { kind: SimulateCaptureDemosaic; fast?: boolean }
214
+ ```
215
+
196
216
  ## SimulateCaptureDngPart
197
217
 
198
218
  One part of a whole-frame DNG (#391): a region render's packed RAW and where its native sites lie (`result.raw`, `result.region`).
@@ -212,6 +232,29 @@ The exact contract is declared below; use the domain guide for assumptions and s
212
232
  export type SimulateCaptureExposureMode = "manual" | "aperture-priority" | "shutter-priority" | "program";
213
233
  ```
214
234
 
235
+ ## SimulateCaptureFastOption
236
+
237
+ The exact contract is declared below; use the domain guide for assumptions and staged integration.
238
+
239
+ ```ts
240
+ export type SimulateCaptureFastOption = typeof SIMULATE_CAPTURE_FAST_OPTIONS[number];
241
+ ```
242
+
243
+ ## SimulateCaptureFastReport
244
+
245
+ `diagnostics.fast` of a capture or display view (#395): what was asked for and what ran.
246
+
247
+ ```ts
248
+ export interface SimulateCaptureFastReport {
249
+ /** True when `fast: true` was given at the top level or in any option's record. */
250
+ requested: boolean;
251
+ /** Each fast-capable option that ran, in {@link SIMULATE_CAPTURE_FAST_OPTIONS} order: true where its fast method ran. */
252
+ applied: Readonly<Partial<Record<SimulateCaptureFastOption, boolean>>>;
253
+ /** `engine-reference` when every option ran exact; `approximation-with-a-priori-bound` when any fast method ran (the WebGPU execution record's values). */
254
+ assurance: "engine-reference" | "approximation-with-a-priori-bound";
255
+ }
256
+ ```
257
+
215
258
  ## SimulateCaptureLensDistortion
216
259
 
217
260
  The exact contract is declared below; use the domain guide for assumptions and staged integration.
@@ -332,8 +375,8 @@ export interface SimulateCaptureOptions {
332
375
  * through `prepareRgbGamutMapping`: constant CIELAB L* and hue, chroma above 90 % of the boundary compressed.
333
376
  */
334
377
  gamutMapping?: "clip" | "perceptual";
335
- /** Default: the 1.0 facade's bilinear RGGB kernels. */
336
- demosaic?: SimulateCaptureDemosaic;
378
+ /** Default: the 1.0 facade's bilinear RGGB kernels. The record form (#395) adds a `fast` override. */
379
+ demosaic?: SimulateCaptureDemosaic | SimulateCaptureDemosaicRecord;
337
380
  /** Default "margin". */
338
381
  borderHandling?: SimulateCaptureBorderHandling;
339
382
  /** DNG only: optional capture-event time (YYYY-MM-DDTHH:mm:ss.sssZ); without it no date tags are written. */
@@ -391,6 +434,13 @@ export interface SimulateCaptureOptions {
391
434
  */
392
435
  pixelAperture?: SimulateCapturePixelAperture;
393
436
  };
437
+ /**
438
+ * Exact or fast (#395). `false` or omitted: every option runs its exact method, the engine reference. `true`: each option
439
+ * listed in {@link SIMULATE_CAPTURE_FAST_OPTIONS} runs its fast method where it has one, a measured, bounded approximation of
440
+ * the exact one; an option without a fast method runs exact. An option's own record `fast` overrides this for that option
441
+ * only. `diagnostics.fast` reports what was requested and what ran. No option has a fast method yet, so every result is exact.
442
+ */
443
+ fast?: boolean;
394
444
  /** Aborting cancels the running task; the promise rejects with a domain error and returns no partial image. */
395
445
  signal?: AbortSignal;
396
446
  /** Called after each committed RAW, development or JPEG tile. Cannot change output. */
@@ -408,10 +458,10 @@ export type SimulateCaptureOutputFormat = "srgb-8" | "srgb-16" | "jpeg" | "png"
408
458
 
409
459
  ## SimulateCapturePixelAperture
410
460
 
411
- Pixel aperture (2.3): centre sampling, or the square photosite integrated with an N × N midpoint rule.
461
+ Pixel aperture (2.3): centre sampling, or the square photosite integrated with an N × N midpoint rule; `fast` (#395) overrides the top-level flag.
412
462
 
413
463
  ```ts
414
- export type SimulateCapturePixelAperture = "point" | "box" | { kind: "box"; samplesPerAxis?: number };
464
+ export type SimulateCapturePixelAperture = "point" | "box" | { kind: "box"; samplesPerAxis?: number; fast?: boolean };
415
465
  ```
416
466
 
417
467
  ## SimulateCaptureProgress
@@ -532,6 +582,8 @@ export interface SimulateCaptureResult {
532
582
  * the user's device.
533
583
  */
534
584
  options: readonly SimulateCaptureCostOption[];
585
+ /** #395: exact or fast, as requested and as run (see {@link SimulateCaptureFastReport}). */
586
+ fast: SimulateCaptureFastReport;
535
587
  };
536
588
  provenance: {
537
589
  scientificStatus: "approximation";
@@ -559,9 +611,9 @@ frequency 1/(2·pitch)).
559
611
 
560
612
  ```ts
561
613
  export type SimulateCaptureSensorAntiAliasing =
562
- | { kind: "four-spot"; separationSites?: number }
563
- | { kind: "two-spot"; axis: "horizontal" | "vertical"; separationSites?: number }
564
- | { kind: "point-splitting"; components: readonly AntiAliasingPointSplitComponent[] };
614
+ | { kind: "four-spot"; separationSites?: number; fast?: boolean }
615
+ | { kind: "two-spot"; axis: "horizontal" | "vertical"; separationSites?: number; fast?: boolean }
616
+ | { kind: "point-splitting"; components: readonly AntiAliasingPointSplitComponent[]; fast?: boolean };
565
617
  ```
566
618
 
567
619
  ## SimulateCaptureWhiteBalance
@@ -11,8 +11,30 @@ setup: use it to render one view in many regions, for example on each worker of
11
11
 
12
12
  ```ts
13
13
  export interface PreparedDisplayView {
14
- /** Renders a view of the prepared request. Renders may run concurrently; they share no state except read-only setup. */
14
+ /**
15
+ * Renders a view of the prepared request. Renders may run concurrently; they share no state except read-only setup and the
16
+ * realm's AHD correction states, which never change a byte (docs/DISPLAY_VIEW.md, "AHD at low signal").
17
+ */
15
18
  render(view: SimulateDisplayViewOptions, renderOptions?: PreparedDisplayViewRenderOptions): Promise<DisplayViewResult>;
19
+ /**
20
+ * 2.10 (#447): the key of this request's AHD low-signal correction states, or null when the request has no AHD
21
+ * (`output.demosaic` other than "ahd"). Every input of the key is fixed when the request is prepared; two prepared views
22
+ * with the same key read the same states.
23
+ */
24
+ correctionKey(): string | null;
25
+ /**
26
+ * 2.10 (#447): the grid keys of every correction state a render of `view` reads (ascending, whether or not this realm holds
27
+ * them), found by a render of the view's region that records the states instead of computing them. No image is returned;
28
+ * it costs about one render whose states are all held. Fails with an InvalidConfigurationError when the request has no AHD.
29
+ */
30
+ collectCorrectionStates(view: SimulateDisplayViewOptions, renderOptions?: PreparedDisplayViewRenderOptions): Promise<DisplayViewCorrectionStateKeys>;
31
+ /**
32
+ * 2.10 (#447): computes the correction states of `gridKeys` (from `collectCorrectionStates`, or a share of them) as a render
33
+ * would, stores them in this realm's cache and returns their values, for {@link bindDisplayViewCorrectionStates} in
34
+ * another realm. States this realm holds are read, not computed. Yields and honours `signal` like `render`. Fails with an
35
+ * InvalidConfigurationError when the request has no AHD or a grid key is out of range.
36
+ */
37
+ computeCorrectionStates(gridKeys: Int32Array, renderOptions?: PreparedDisplayViewRenderOptions): Promise<DisplayViewCorrectionStateSet>;
16
38
  }
17
39
  ```
18
40
 
@@ -51,6 +51,11 @@ export interface ImageKernelExecution {
51
51
  fallbackReason: ImageKernelFallbackReason | null;
52
52
  arithmetic: "float64" | "float32";
53
53
  assurance: "engine-reference" | "approximation-with-a-priori-bound";
54
+ /**
55
+ * The exact-or-fast flag in the facade's words (#395): false for `cpu-reference` (the engine reference), true for
56
+ * `webgpu-f32` (a bounded approximation). `backend` still names where the work ran.
57
+ */
58
+ fast: boolean;
54
59
  /**
55
60
  * True only for `cpu-reference`. Bit-exact identities (SHA-256 artifact bindings, byte-parity fixtures,
56
61
  * cross-engine determinism hashes) are CPU-only and must never be computed from a `webgpu-f32` result.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@photivra/engine",
3
- "version": "2.9.0",
3
+ "version": "2.10.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",