@photivra/engine 2.12.0 → 2.14.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 (148) hide show
  1. package/CHANGELOG.md +144 -1
  2. package/CITATION.cff +1 -1
  3. package/README.md +7 -7
  4. package/SECURITY.md +1 -1
  5. package/THIRD_PARTY.md +3 -0
  6. package/dist/camera/lens-projection.js +2 -1
  7. package/dist/camera/lens-projection.js.map +1 -1
  8. package/dist/capture/dng-import.js +1 -1
  9. package/dist/capture/dng-import.js.map +1 -1
  10. package/dist/capture/export-jpeg.d.ts +1 -1
  11. package/dist/capture/export-jpeg.js +6 -4
  12. package/dist/capture/export-jpeg.js.map +1 -1
  13. package/dist/capture/host-yield-cadence.js +1 -1
  14. package/dist/capture/host-yield-cadence.js.map +1 -1
  15. package/dist/capture/native-environment-optical-stage.js +1 -1
  16. package/dist/capture/native-environment-optical-stage.js.map +1 -1
  17. package/dist/capture/native-raw.js +1 -1
  18. package/dist/capture/native-raw.js.map +1 -1
  19. package/dist/capture/packed-sensor-raw.js +3 -3
  20. package/dist/capture/packed-sensor-raw.js.map +1 -1
  21. package/dist/capture/sensor-raw-producer.js +1 -1
  22. package/dist/capture/sensor-raw-producer.js.map +1 -1
  23. package/dist/color/capture-color.js +3 -3
  24. package/dist/color/capture-color.js.map +1 -1
  25. package/dist/color/chromatic-adaptation.js +2 -2
  26. package/dist/color/chromatic-adaptation.js.map +1 -1
  27. package/dist/color/color-matching-functions.js +1 -1
  28. package/dist/color/color-matching-functions.js.map +1 -1
  29. package/dist/color/colorimetry-math.js +2 -2
  30. package/dist/color/colorimetry-math.js.map +1 -1
  31. package/dist/color/illuminants.js +3 -3
  32. package/dist/color/illuminants.js.map +1 -1
  33. package/dist/color/rgb-color-spaces.js +1 -1
  34. package/dist/color/rgb-color-spaces.js.map +1 -1
  35. package/dist/color/sensor-color-development.js +1 -1
  36. package/dist/color/sensor-color-development.js.map +1 -1
  37. package/dist/core/record-validation.js +3 -3
  38. package/dist/core/record-validation.js.map +1 -1
  39. package/dist/core/version.d.ts +1 -1
  40. package/dist/core/version.js +1 -1
  41. package/dist/core/version.js.map +1 -1
  42. package/dist/equipment/generic-prime-lenses.js +3 -3
  43. package/dist/equipment/generic-prime-lenses.js.map +1 -1
  44. package/dist/equipment/generic-tier-assets.d.ts +23 -1
  45. package/dist/equipment/generic-tier-assets.js +58 -30
  46. package/dist/equipment/generic-tier-assets.js.map +1 -1
  47. package/dist/equipment/generic-tier-presets.d.ts +6 -3
  48. package/dist/equipment/generic-tier-presets.js +26 -13
  49. package/dist/equipment/generic-tier-presets.js.map +1 -1
  50. package/dist/exposure/auto-iso-slowest-shutter.d.ts +120 -0
  51. package/dist/exposure/auto-iso-slowest-shutter.js +217 -0
  52. package/dist/exposure/auto-iso-slowest-shutter.js.map +1 -0
  53. package/dist/exposure/exposure-mode-resolver.d.ts +57 -1
  54. package/dist/exposure/exposure-mode-resolver.js +238 -33
  55. package/dist/exposure/exposure-mode-resolver.js.map +1 -1
  56. package/dist/exposure/flash-ttl.js +1 -1
  57. package/dist/exposure/flash-ttl.js.map +1 -1
  58. package/dist/exposure/flash.js +1 -1
  59. package/dist/exposure/flash.js.map +1 -1
  60. package/dist/facade/chart-material-layers.js +2 -2
  61. package/dist/facade/chart-material-layers.js.map +1 -1
  62. package/dist/facade/chart-radiance-batch.js +1 -1
  63. package/dist/facade/chart-radiance-batch.js.map +1 -1
  64. package/dist/facade/chart-scenes.d.ts +45 -8
  65. package/dist/facade/chart-scenes.js +101 -44
  66. package/dist/facade/chart-scenes.js.map +1 -1
  67. package/dist/facade/color-patches.d.ts +129 -0
  68. package/dist/facade/color-patches.js +209 -0
  69. package/dist/facade/color-patches.js.map +1 -0
  70. package/dist/facade/diffraction-provider.js +12 -13
  71. package/dist/facade/diffraction-provider.js.map +1 -1
  72. package/dist/facade/display-view-gpu.js +1 -1
  73. package/dist/facade/display-view-gpu.js.map +1 -1
  74. package/dist/facade/display-view.d.ts +27 -0
  75. package/dist/facade/display-view.js +234 -65
  76. package/dist/facade/display-view.js.map +1 -1
  77. package/dist/facade/scene-radiance.js +2 -2
  78. package/dist/facade/scene-radiance.js.map +1 -1
  79. package/dist/facade/simulate-capture.d.ts +139 -12
  80. package/dist/facade/simulate-capture.js +209 -36
  81. package/dist/facade/simulate-capture.js.map +1 -1
  82. package/dist/facade/simulate-display-view.js +2 -2
  83. package/dist/facade/simulate-display-view.js.map +1 -1
  84. package/dist/gpu/chart-composite-gpu.js +2 -2
  85. package/dist/gpu/chart-composite-gpu.js.map +1 -1
  86. package/dist/gpu/display-view-composite-material-module.js +1 -1
  87. package/dist/gpu/display-view-composite-material-module.js.map +1 -1
  88. package/dist/gpu/display-view-quality-gpu.d.ts +2 -1
  89. package/dist/gpu/display-view-quality-gpu.js +24 -14
  90. package/dist/gpu/display-view-quality-gpu.js.map +1 -1
  91. package/dist/gpu/image-kernel-execution.js +2 -2
  92. package/dist/gpu/image-kernel-execution.js.map +1 -1
  93. package/dist/gpu/temporal-sum-gpu.js +23 -23
  94. package/dist/gpu/webgpu-runtime.js +1 -1
  95. package/dist/gpu/webgpu-runtime.js.map +1 -1
  96. package/dist/gpu/wgsl-chart-composite-kernel.js +318 -318
  97. package/dist/gpu/wgsl-chart-composite-kernel.js.map +1 -1
  98. package/dist/gpu/wgsl-chart-kernel.js +117 -117
  99. package/dist/gpu/wgsl-chart-kernel.js.map +1 -1
  100. package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +13 -1
  101. package/dist/gpu/wgsl-display-view-quality-kernel.js +522 -488
  102. package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
  103. package/dist/gpu/wgsl-display-view-speed-kernel.js +248 -248
  104. package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
  105. package/dist/gpu/wgsl-kernels.js +203 -203
  106. package/dist/gpu/wgsl-kernels.js.map +1 -1
  107. package/dist/gpu/wgsl-sensor-kernel.js +302 -302
  108. package/dist/gpu/wgsl-sensor-kernel.js.map +1 -1
  109. package/dist/index.d.ts +8 -5
  110. package/dist/index.js +6 -3
  111. package/dist/index.js.map +1 -1
  112. package/dist/motion/temporal-exposure-sum.js +1 -1
  113. package/dist/motion/temporal-exposure-sum.js.map +1 -1
  114. package/dist/optics/diffraction-psf-profile.js +4 -4
  115. package/dist/optics/diffraction-psf-profile.js.map +1 -1
  116. package/dist/optics/front-of-lens-filter.js +1 -1
  117. package/dist/optics/front-of-lens-filter.js.map +1 -1
  118. package/dist/optics/irradiance-convolution.d.ts +10 -0
  119. package/dist/optics/irradiance-convolution.js +49 -14
  120. package/dist/optics/irradiance-convolution.js.map +1 -1
  121. package/dist/output/native-capture-sdr.js +1 -1
  122. package/dist/output/native-capture-sdr.js.map +1 -1
  123. package/dist/output/png-encoder.js +2 -2
  124. package/dist/output/png-encoder.js.map +1 -1
  125. package/dist/output/print-jpeg.js +13 -10
  126. package/dist/output/print-jpeg.js.map +1 -1
  127. package/dist/output/text-metadata.d.ts +22 -2
  128. package/dist/output/text-metadata.js +58 -9
  129. package/dist/output/text-metadata.js.map +1 -1
  130. package/dist/sensor/fixed-pattern-noise.js +1 -1
  131. package/dist/sensor/fixed-pattern-noise.js.map +1 -1
  132. package/dist/sensor/readout-exposure-linkage.js +1 -1
  133. package/dist/sensor/readout-exposure-linkage.js.map +1 -1
  134. package/docs/API_REFERENCE.md +49 -1
  135. package/docs/QUICK_START.md +104 -9
  136. package/docs/USAGE.md +241 -2
  137. package/docs/api/core-version.md +1 -1
  138. package/docs/api/equipment-generic-tier-assets.md +41 -1
  139. package/docs/api/equipment-generic-tier-presets.md +11 -3
  140. package/docs/api/exports.json +172 -2
  141. package/docs/api/exposure-auto-iso-slowest-shutter.md +139 -0
  142. package/docs/api/exposure-exposure-mode-resolver.md +68 -0
  143. package/docs/api/facade-chart-scenes.md +36 -5
  144. package/docs/api/facade-color-patches.md +150 -0
  145. package/docs/api/facade-simulate-capture.md +140 -9
  146. package/docs/api/output-text-metadata.md +34 -0
  147. package/llms.txt +1 -0
  148. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"generic-prime-lenses.js","sourceRoot":"","sources":["../../src/equipment/generic-prime-lenses.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Generic prime lens family (2.3): educational lenses named by their full-frame-equivalent focal length,\n * written for this engine. They are not real products and carry no brand. Each lens is defined by three\n * rules only:\n * - actual focal length = equivalent focal length ÷ the sensor's diagonal crop factor\n * (`calculateEquivalentFocalLength35Mm`, 36 × 24 mm reference);\n * - an f-number range by focal-length class (widest aperture) and focal length (narrowest aperture);\n * - a minimum focus distance max(0.10 m, f·(1 + 1/0.15)): the thin-lens object distance at 0.15×\n * magnification (d = f(1 + 1/m)), but never closer than 10 cm. A generic thin-lens approximation, not a\n * measured lens.\n * @see docs/QUICK_START.md, \"Generic prime lenses\".\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireInputKeys, requireInputObject } from \"../core/record-validation.js\";\nimport { calculateEquivalentFocalLength35Mm } from \"../camera/equivalent-focal-length.js\";\n\n/** Full-frame-equivalent focal lengths of the generic prime family, mm. */\nexport const GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM = Object.freeze([10, 12, 14, 16, 20, 24, 28, 35, 40, 50, 85, 105, 135, 200, 300, 400, 500, 600, 800, 1200] as const);\nexport type GenericPrimeEquivalentFocalLengthMm = typeof GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM[number];\n/**\n * The marked third-stop f-numbers (the conventional rounded values of N = 2^(k/6), k = 0, 1, …), from f/1 to f/32.\n * A lens's `fNumbers` are those within its range; any f-number inside the range is accepted.\n */\nexport const GENERIC_PRIME_THIRD_STOP_F_NUMBERS = Object.freeze([1, 1.1, 1.2, 1.4, 1.6, 1.8, 2, 2.2, 2.5, 2.8, 3.2, 3.5, 4, 4.5, 5, 5.6, 6.3, 7.1, 8, 9, 10, 11,\n 13, 14, 16, 18, 20, 22, 25, 29, 32] as const);\n/** Minimum focus rule: the object distance at this magnification, but at least `minimumDistanceM`. */\nexport const GENERIC_PRIME_MINIMUM_FOCUS = Object.freeze({ magnification: 0.15, minimumDistanceM: 0.1 });\n\n/** Widest f-number by equivalent focal length (inclusive upper bounds of each class). */\nconst WIDEST: readonly (readonly [number, number])[] = [[16, 2.8], [28, 1.8], [85, 1.4], [135, 2], [300, 2.8], [600, 4], [800, 5.6], [1200, 8]];\n/** Narrowest f-number by equivalent focal length. */\nconst NARROWEST: readonly (readonly [number, number])[] = [[16, 16], [135, 22], [1200, 32]];\n\nexport interface GenericPrimeLens {\n /** Public opaque id, for example \"generic-prime-50mm-equivalent\". */\n lensId: string;\n equivalentFocalLengthMm: GenericPrimeEquivalentFocalLengthMm;\n /** Physical focal length for this sensor: equivalent ÷ crop factor. */\n focalLengthMm: number;\n /** Diagonal crop factor of the sensor (36 × 24 mm = 1). */\n cropFactor35Mm: number;\n /** Widest aperture (smallest f-number) and narrowest aperture. */\n widestFNumber: number;\n narrowestFNumber: number;\n /** The marked third-stop f-numbers within the range. */\n fNumbers: readonly number[];\n /** max(0.10 m, f·(1 + 1/0.15)), metres from the lens (thin lens). */\n minimumFocusDistanceM: number;\n /** Magnification at the minimum focus distance, f/(d − f). */\n maximumMagnification: number;\n scientificStatus: \"approximation\";\n limitations: readonly string[];\n}\n\n/** Minimum focus distance of a generic prime of physical focal length `focalLengthMm`: max(0.10 m, f·(1 + 1/0.15)). */\nexport function calculateGenericPrimeMinimumFocusDistanceM(focalLengthMm: number): number {\n if (typeof focalLengthMm !== \"number\" || !Number.isFinite(focalLengthMm) || focalLengthMm <= 0) throw new InvalidConfigurationError(\"focalLengthMm must be a positive finite number.\");\n return Math.max(GENERIC_PRIME_MINIMUM_FOCUS.minimumDistanceM, focalLengthMm / 1000 * (1 + 1 / GENERIC_PRIME_MINIMUM_FOCUS.magnification));\n}\n\n/**\n * Resolves a generic prime for a sensor: its actual focal length, f-number range, marked f-numbers and minimum focus.\n * `activeImagingArea` is the sensor's active capture area in millimetres.\n */\nexport function resolveGenericPrimeLens(input: { equivalentFocalLengthMm: number; activeImagingArea: { widthMm: number; heightMm: number } }): GenericPrimeLens {\n requireInputObject(input, \"resolveGenericPrimeLens input\");\n requireInputKeys(input, \"resolveGenericPrimeLens\", [\"equivalentFocalLengthMm\", \"activeImagingArea\"]);\n const equivalent = input.equivalentFocalLengthMm;\n if (!(GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM as readonly number[]).includes(equivalent))\n throw new InvalidConfigurationError(\"equivalentFocalLengthMm must be one of the generic primes: \" + GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM.join(\", \") + \" mm.\");\n requireInputObject(input.activeImagingArea, \"activeImagingArea\");\n const crop = calculateEquivalentFocalLength35Mm({ focalLengthMm: 1, activeImagingArea: { widthMm: input.activeImagingArea.widthMm, heightMm: input.activeImagingArea.heightMm } }).value.cropFactor35Mm;\n const focalLengthMm = equivalent / crop;\n const widest = WIDEST.find(([bound]) => equivalent <= bound)![1], narrowest = NARROWEST.find(([bound]) => equivalent <= bound)![1];\n const minimumFocusDistanceM = calculateGenericPrimeMinimumFocusDistanceM(focalLengthMm), f = focalLengthMm / 1000;\n return Object.freeze({ lensId: \"generic-prime-\" + equivalent + \"mm-equivalent\", equivalentFocalLengthMm: equivalent as GenericPrimeEquivalentFocalLengthMm, focalLengthMm,\n cropFactor35Mm: crop, widestFNumber: widest, narrowestFNumber: narrowest,\n fNumbers: Object.freeze(GENERIC_PRIME_THIRD_STOP_F_NUMBERS.filter((n) => n >= widest && n <= narrowest)), minimumFocusDistanceM,\n maximumMagnification: f / (minimumFocusDistanceM - f), scientificStatus: \"approximation\" as const,\n limitations: Object.freeze([\"Generic educational prime defined by focal length, f-number range and a thin-lens minimum-focus rule; not a real product.\",\n \"Minimum focus max(0.10 m, f·(1 + 1/0.15)) is a thin-lens approximation measured from the lens; real lenses differ (internal focusing, pupil positions, focus breathing).\"]) });\n}\n"]}
1
+ {"version":3,"file":"generic-prime-lenses.js","sourceRoot":"","sources":["../../src/equipment/generic-prime-lenses.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,kCAAkC,EAAE,MAAM,sCAAsC,CAAC;AAE1F,2EAA2E;AAC3E,MAAM,CAAC,MAAM,yCAAyC,GAAG,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAU,CAAC,CAAC;AAE5L;;;GAGG;AACH,MAAM,CAAC,MAAM,kCAAkC,GAAG,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE;IAC7K,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAU,CAAC,CAAC;AAChD,sGAAsG;AACtG,MAAM,CAAC,MAAM,2BAA2B,GAAG,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC;AAEzH,yFAAyF;AACzF,MAAM,MAAM,GAA2C,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAChJ,qDAAqD;AACrD,MAAM,SAAS,GAA2C,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;AAuB5F,uHAAuH;AACvH,MAAM,UAAU,0CAA0C,CAAC,aAAqB;IAC9E,IAAI,OAAO,aAAa,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,aAAa,IAAI,CAAC;QAAE,MAAM,IAAI,yBAAyB,CAAC,iDAAiD,CAAC,CAAC;IACvL,OAAO,IAAI,CAAC,GAAG,CAAC,2BAA2B,CAAC,gBAAgB,EAAE,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,2BAA2B,CAAC,aAAa,CAAC,CAAC,CAAC;AAC5I,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAoG;IAC1I,kBAAkB,CAAC,KAAK,EAAE,+BAA+B,CAAC,CAAC;IAC3D,gBAAgB,CAAC,KAAK,EAAE,yBAAyB,EAAE,CAAC,yBAAyB,EAAE,mBAAmB,CAAC,CAAC,CAAC;IACrG,MAAM,UAAU,GAAG,KAAK,CAAC,uBAAuB,CAAC;IACjD,IAAI,CAAE,yCAA+D,CAAC,QAAQ,CAAC,UAAU,CAAC;QACxF,MAAM,IAAI,yBAAyB,CAAC,6DAA6D,GAAG,yCAAyC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;IACrK,kBAAkB,CAAC,KAAK,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,CAAC;IACjE,MAAM,IAAI,GAAG,kCAAkC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,iBAAiB,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,iBAAiB,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,iBAAiB,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC;IACxM,MAAM,aAAa,GAAG,UAAU,GAAG,IAAI,CAAC;IACxC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,UAAU,IAAI,KAAK,CAAE,CAAC,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,UAAU,IAAI,KAAK,CAAE,CAAC,CAAC,CAAC,CAAC;IACnI,MAAM,qBAAqB,GAAG,0CAA0C,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG,aAAa,GAAG,IAAI,CAAC;IAClH,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,gBAAgB,GAAG,UAAU,GAAG,eAAe,EAAE,uBAAuB,EAAE,UAAiD,EAAE,aAAa;QACvK,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS;QACxE,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,kCAAkC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,SAAS,CAAC,CAAC,EAAE,qBAAqB;QAC/H,oBAAoB,EAAE,CAAC,GAAG,CAAC,qBAAqB,GAAG,CAAC,CAAC,EAAE,gBAAgB,EAAE,eAAwB;QACjG,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,2HAA2H;YACrJ,0KAA0K,CAAC,CAAC,EAAE,CAAC,CAAC;AACtL,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Generic prime lens family (2.3): educational lenses named by their full-frame-equivalent focal length,\n * written for this engine. They are not real products and carry no brand. Each lens is defined by three\n * rules only:\n * - actual focal length = equivalent focal length ÷ the sensor's diagonal crop factor\n * (`calculateEquivalentFocalLength35Mm`, 36 × 24 mm reference);\n * - an f-number range by focal-length class (widest aperture) and focal length (narrowest aperture);\n * - a minimum focus distance max(0.10 m, f·(1 + 1/0.15)): the thin-lens object distance at 0.15×\n * magnification (d = f(1 + 1/m)), but never closer than 10 cm. A generic thin-lens approximation, not a\n * measured lens.\n * @see docs/QUICK_START.md, \"Generic prime lenses\".\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireInputKeys, requireInputObject } from \"../core/record-validation.js\";\nimport { calculateEquivalentFocalLength35Mm } from \"../camera/equivalent-focal-length.js\";\n\n/** Full-frame-equivalent focal lengths of the generic prime family, mm. */\nexport const GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM = /* @__PURE__ */ Object.freeze([10, 12, 14, 16, 20, 24, 28, 35, 40, 50, 85, 105, 135, 200, 300, 400, 500, 600, 800, 1200] as const);\nexport type GenericPrimeEquivalentFocalLengthMm = typeof GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM[number];\n/**\n * The marked third-stop f-numbers (the conventional rounded values of N = 2^(k/6), k = 0, 1, …), from f/1 to f/32.\n * A lens's `fNumbers` are those within its range; any f-number inside the range is accepted.\n */\nexport const GENERIC_PRIME_THIRD_STOP_F_NUMBERS = /* @__PURE__ */ Object.freeze([1, 1.1, 1.2, 1.4, 1.6, 1.8, 2, 2.2, 2.5, 2.8, 3.2, 3.5, 4, 4.5, 5, 5.6, 6.3, 7.1, 8, 9, 10, 11,\n 13, 14, 16, 18, 20, 22, 25, 29, 32] as const);\n/** Minimum focus rule: the object distance at this magnification, but at least `minimumDistanceM`. */\nexport const GENERIC_PRIME_MINIMUM_FOCUS = /* @__PURE__ */ Object.freeze({ magnification: 0.15, minimumDistanceM: 0.1 });\n\n/** Widest f-number by equivalent focal length (inclusive upper bounds of each class). */\nconst WIDEST: readonly (readonly [number, number])[] = [[16, 2.8], [28, 1.8], [85, 1.4], [135, 2], [300, 2.8], [600, 4], [800, 5.6], [1200, 8]];\n/** Narrowest f-number by equivalent focal length. */\nconst NARROWEST: readonly (readonly [number, number])[] = [[16, 16], [135, 22], [1200, 32]];\n\nexport interface GenericPrimeLens {\n /** Public opaque id, for example \"generic-prime-50mm-equivalent\". */\n lensId: string;\n equivalentFocalLengthMm: GenericPrimeEquivalentFocalLengthMm;\n /** Physical focal length for this sensor: equivalent ÷ crop factor. */\n focalLengthMm: number;\n /** Diagonal crop factor of the sensor (36 × 24 mm = 1). */\n cropFactor35Mm: number;\n /** Widest aperture (smallest f-number) and narrowest aperture. */\n widestFNumber: number;\n narrowestFNumber: number;\n /** The marked third-stop f-numbers within the range. */\n fNumbers: readonly number[];\n /** max(0.10 m, f·(1 + 1/0.15)), metres from the lens (thin lens). */\n minimumFocusDistanceM: number;\n /** Magnification at the minimum focus distance, f/(d − f). */\n maximumMagnification: number;\n scientificStatus: \"approximation\";\n limitations: readonly string[];\n}\n\n/** Minimum focus distance of a generic prime of physical focal length `focalLengthMm`: max(0.10 m, f·(1 + 1/0.15)). */\nexport function calculateGenericPrimeMinimumFocusDistanceM(focalLengthMm: number): number {\n if (typeof focalLengthMm !== \"number\" || !Number.isFinite(focalLengthMm) || focalLengthMm <= 0) throw new InvalidConfigurationError(\"focalLengthMm must be a positive finite number.\");\n return Math.max(GENERIC_PRIME_MINIMUM_FOCUS.minimumDistanceM, focalLengthMm / 1000 * (1 + 1 / GENERIC_PRIME_MINIMUM_FOCUS.magnification));\n}\n\n/**\n * Resolves a generic prime for a sensor: its actual focal length, f-number range, marked f-numbers and minimum focus.\n * `activeImagingArea` is the sensor's active capture area in millimetres.\n */\nexport function resolveGenericPrimeLens(input: { equivalentFocalLengthMm: number; activeImagingArea: { widthMm: number; heightMm: number } }): GenericPrimeLens {\n requireInputObject(input, \"resolveGenericPrimeLens input\");\n requireInputKeys(input, \"resolveGenericPrimeLens\", [\"equivalentFocalLengthMm\", \"activeImagingArea\"]);\n const equivalent = input.equivalentFocalLengthMm;\n if (!(GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM as readonly number[]).includes(equivalent))\n throw new InvalidConfigurationError(\"equivalentFocalLengthMm must be one of the generic primes: \" + GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM.join(\", \") + \" mm.\");\n requireInputObject(input.activeImagingArea, \"activeImagingArea\");\n const crop = calculateEquivalentFocalLength35Mm({ focalLengthMm: 1, activeImagingArea: { widthMm: input.activeImagingArea.widthMm, heightMm: input.activeImagingArea.heightMm } }).value.cropFactor35Mm;\n const focalLengthMm = equivalent / crop;\n const widest = WIDEST.find(([bound]) => equivalent <= bound)![1], narrowest = NARROWEST.find(([bound]) => equivalent <= bound)![1];\n const minimumFocusDistanceM = calculateGenericPrimeMinimumFocusDistanceM(focalLengthMm), f = focalLengthMm / 1000;\n return Object.freeze({ lensId: \"generic-prime-\" + equivalent + \"mm-equivalent\", equivalentFocalLengthMm: equivalent as GenericPrimeEquivalentFocalLengthMm, focalLengthMm,\n cropFactor35Mm: crop, widestFNumber: widest, narrowestFNumber: narrowest,\n fNumbers: Object.freeze(GENERIC_PRIME_THIRD_STOP_F_NUMBERS.filter((n) => n >= widest && n <= narrowest)), minimumFocusDistanceM,\n maximumMagnification: f / (minimumFocusDistanceM - f), scientificStatus: \"approximation\" as const,\n limitations: Object.freeze([\"Generic educational prime defined by focal length, f-number range and a thin-lens minimum-focus rule; not a real product.\",\n \"Minimum focus max(0.10 m, f·(1 + 1/0.15)) is a thin-lens approximation measured from the lens; real lenses differ (internal focusing, pupil positions, focus breathing).\"]) });\n}\n"]}
@@ -79,11 +79,33 @@ export interface GenericEquipmentTierPreset {
79
79
  tier: GenericEquipmentTier;
80
80
  label: "Consumer" | "Prosumer" | "Professional";
81
81
  presetId: string;
82
- presetVersion: "2.0.0";
82
+ presetVersion: GenericTierPresetVersion;
83
83
  scientificStatus: "approximation";
84
84
  evidence: readonly EvidenceProvenance[];
85
85
  body: GenericTierBodyAssets;
86
86
  lens: GenericTierLensAssets;
87
87
  tradeoffs: readonly string[];
88
88
  }
89
+ /**
90
+ * The exact versions of the generic tier presets (no "latest" alias). 2.1.0 (2.14, round 5) adds the third-stop ISO
91
+ * settings; 2.0.0 is kept, whole-stop, so saved selections and records of it still resolve to exactly what they named.
92
+ */
93
+ export type GenericTierPresetVersion = "2.0.0" | "2.1.0";
94
+ /** Whole-stop ISO settings of the 2.0.0 bodies (each body's list stops at its maximum). */
95
+ export declare const GENERIC_WHOLE_STOP_ISO_SETTINGS: readonly [100, 200, 400, 800, 1600, 3200, 6400, 12800, 25600];
96
+ /**
97
+ * Third-stop ISO settings of the 2.1.0 bodies: the conventional rounded markings of S = 100·2^(k/3), k = 0 … 24 (125 for
98
+ * 126.0, 160 for 158.7 …; each within 2 % of the exact value). The engine takes the setting as the exact ISO speed.
99
+ */
100
+ /**
101
+ * The standard third-stop shutter times, seconds, from 1/8000 s to 30 s: the conventional markings of t = 2^(k/3) s
102
+ * (1/8000 for 2^−13, 1/6 for 2^−8/3, 0.3 for 2^−5/3, 30 for 2^5; each within 7 % of the exact value). The generic bodies'
103
+ * shutters are continuous over 1/8000–30 s and take any time as exact, so these are the values to offer in a third-stop
104
+ * dial, not a restriction.
105
+ */
106
+ export declare const GENERIC_THIRD_STOP_SHUTTER_SECONDS: readonly [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.3, 1.6, 2, 2.5, 3.2, 4, 5, 6, 8, 10, 13, 15, 20, 25, 30];
107
+ export declare const GENERIC_THIRD_STOP_ISO_SETTINGS: readonly [100, 125, 160, 200, 250, 320, 400, 500, 640, 800, 1000, 1250, 1600, 2000, 2500, 3200, 4000, 5000, 6400, 8000, 10000, 12800, 16000, 20000, 25600];
108
+ /** The presets of the current version, 2.1.0 (third-stop ISO settings). */
89
109
  export declare const GENERIC_TIER_ASSETS: readonly GenericEquipmentTierPreset[];
110
+ /** The presets of an exact version; 2.0.0 (whole-stop ISO) is built on first use. */
111
+ export declare function genericTierAssets(version: GenericTierPresetVersion): readonly GenericEquipmentTierPreset[];
@@ -16,7 +16,24 @@ const evidence = [{ sourceOrigin: "photivra", sourceReference: "photivra:generic
16
16
  reuseStatus: "photivra-owned" }];
17
17
  const limitations = ["Synthetic educational design values; no named camera/lens calibration or population ranking."];
18
18
  const fact = (value) => ({ value, evidence });
19
- const version = "2.0.0";
19
+ /** Whole-stop ISO settings of the 2.0.0 bodies (each body's list stops at its maximum). */
20
+ export const GENERIC_WHOLE_STOP_ISO_SETTINGS = /* @__PURE__ */ Object.freeze([100, 200, 400, 800, 1600, 3200, 6400, 12800, 25600]);
21
+ /**
22
+ * Third-stop ISO settings of the 2.1.0 bodies: the conventional rounded markings of S = 100·2^(k/3), k = 0 … 24 (125 for
23
+ * 126.0, 160 for 158.7 …; each within 2 % of the exact value). The engine takes the setting as the exact ISO speed.
24
+ */
25
+ /**
26
+ * The standard third-stop shutter times, seconds, from 1/8000 s to 30 s: the conventional markings of t = 2^(k/3) s
27
+ * (1/8000 for 2^−13, 1/6 for 2^−8/3, 0.3 for 2^−5/3, 30 for 2^5; each within 7 % of the exact value). The generic bodies'
28
+ * shutters are continuous over 1/8000–30 s and take any time as exact, so these are the values to offer in a third-stop
29
+ * dial, not a restriction.
30
+ */
31
+ export const GENERIC_THIRD_STOP_SHUTTER_SECONDS = /* @__PURE__ */ Object.freeze([1 / 8000, 1 / 6400, 1 / 5000, 1 / 4000, 1 / 3200, 1 / 2500, 1 / 2000,
32
+ 1 / 1600, 1 / 1250, 1 / 1000, 1 / 800, 1 / 640, 1 / 500, 1 / 400, 1 / 320, 1 / 250, 1 / 200, 1 / 160, 1 / 125, 1 / 100, 1 / 80, 1 / 60, 1 / 50, 1 / 40,
33
+ 1 / 30, 1 / 25, 1 / 20, 1 / 15, 1 / 13, 1 / 10, 1 / 8, 1 / 6, 1 / 5, 1 / 4, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.3, 1.6, 2, 2.5, 3.2, 4, 5, 6, 8, 10, 13,
34
+ 15, 20, 25, 30]);
35
+ export const GENERIC_THIRD_STOP_ISO_SETTINGS = /* @__PURE__ */ Object.freeze([100, 125, 160, 200, 250, 320, 400, 500, 640, 800, 1000, 1250, 1600,
36
+ 2000, 2500, 3200, 4000, 5000, 6400, 8000, 10000, 12800, 16000, 20000, 25600]);
20
37
  const disk = [0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0];
21
38
  const clipped = [0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0];
22
39
  const clippedMore = [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0];
@@ -24,8 +41,8 @@ const near = [0, 0, .12, 0, 0, 0, .06, 0, .06, 0, .12, 0, -.04, 0, .12, 0, .06,
24
41
  const flat = Array(25).fill(0);
25
42
  const far = near.map((v) => -v);
26
43
  /** Used only to build data. Tier labels never enter any scientific equation. */
27
- function bodyAssets(id, isoMax, cadence, frames, sensor, dataReadoutSeconds, gain, maxAngle, continuousAf, advancedPolicies) {
28
- const isoValues = [100, 200, 400, 800, 1600, 3200, 6400, 12800, 25600].filter((v) => v <= isoMax);
44
+ function bodyAssets(version, id, isoMax, cadence, frames, sensor, dataReadoutSeconds, gain, maxAngle, continuousAf, advancedPolicies) {
45
+ const isoValues = (version === "2.0.0" ? GENERIC_WHOLE_STOP_ISO_SETTINGS : GENERIC_THIRD_STOP_ISO_SETTINGS).filter((v) => v <= isoMax);
29
46
  const exposure = parseGenericBodyExposureCapabilityProfile({ schemaVersion: "0.1.0", profileId: id + ":exposure", profileVersion: version,
30
47
  scientificStatus: "approximation", evidence, shutter: { durationSecondsRange: fact({ minimum: 1 / 8000, maximum: 30 }), settingGrid: { kind: "continuous-within-range" } },
31
48
  iso: { range: fact({ minimum: 100, maximum: isoMax }), settingGrid: { kind: "discrete-values", values: fact(isoValues) }, autoIso: fact("supported") } });
@@ -97,7 +114,7 @@ function bodyAssets(id, isoMax, cadence, frames, sensor, dataReadoutSeconds, gai
97
114
  captureModeId: "native-still", timingProfileId: timingId, supportedOrdinarySyncModes: ["front-curtain", "rear-curtain"],
98
115
  highSpeedSyncSupported: false, ordinarySyncRequiresWholeActiveFrameSimultaneouslyExposed: true, evidence, limitations }) };
99
116
  }
100
- function lensAssets(id, r) {
117
+ function lensAssets(version, id, r) {
101
118
  return { form: "prime", exposure: parseGenericLensExposureCapabilityProfile({ schemaVersion: "0.1.0", profileId: id + ":exposure", profileVersion: version,
102
119
  scientificStatus: "approximation", evidence, focalLengthMmRange: fact({ minimum: 50, maximum: 50 }), aperture: { widestAvailableFNumber: {
103
120
  kind: "constant", fNumber: fact(4)
@@ -109,30 +126,41 @@ function lensAssets(id, r) {
109
126
  }
110
127
  const common = { focalLengthMm: 50, aperture: 4, focusDistanceM: 5, wavelengthNm: 550,
111
128
  normalizationRadiusMm: Math.hypot(18, 12), correctionCaFraction: .8 };
112
- export const GENERIC_TIER_ASSETS = [
113
- { tier: "consumer", label: "Consumer", presetId: "photivra-consumer", presetVersion: version, scientificStatus: "approximation", evidence,
114
- body: bodyAssets("photivra-consumer-body", 6400, 4, 8, { bitDepth: 12, blackLevelCode: 256, saturationElectrons: 20000,
115
- maximumAnalogGain: 32, lowGainReadNoise: 6, highGainReadNoise: 2.5, highGainFromIso: 800, highGainMaximumCharge: 6000,
116
- prnu: .01, dsnu: .3, hotFraction: 2e-4, hotMultiplier: 50, rowRms: .6, columnRms: .4, instanceSeed: 0x51ed270b }, .03, .35, .005, false, false),
117
- lens: lensAssets("photivra-consumer-prime", { ...common, distortionK1: -.06, lateralCaK1Offset: .008, vignettingR2: -.5,
118
- breathingProjectionScale: 1.03, transmission: .75, correctionGainStrength: .8, ghostPowerFraction: .006, veilPowerFraction: .012,
119
- pupilAmplitudeByField: [disk, clipped, clippedMore], pupilOpdMicrometersByDefocus: [near, flat, far], pupilThroughputByField: [1, .85, .65] }),
120
- tradeoffs: ["Limited continuous AF; heavier digital correction and edge pupil clipping in matched reference."] },
121
- { tier: "prosumer", label: "Prosumer", presetId: "photivra-prosumer", presetVersion: version, scientificStatus: "approximation", evidence,
122
- body: bodyAssets("photivra-prosumer-body", 12800, 8, 16, { bitDepth: 14, blackLevelCode: 1024, saturationElectrons: 40000,
123
- maximumAnalogGain: 64, lowGainReadNoise: 3, highGainReadNoise: 1.4, highGainFromIso: 800, highGainMaximumCharge: 12000,
124
- prnu: .006, dsnu: .2, hotFraction: 1e-4, hotMultiplier: 40, rowRms: .3, columnRms: .2, instanceSeed: 0x2c1b3c6d }, .015, .65, .01, true, true),
125
- lens: lensAssets("photivra-prosumer-prime", { ...common, distortionK1: -.025, lateralCaK1Offset: .004, vignettingR2: -.25,
126
- breathingProjectionScale: 1.015, transmission: .85, correctionGainStrength: .6, ghostPowerFraction: .003, veilPowerFraction: .006,
127
- pupilAmplitudeByField: [disk, disk, clipped], pupilOpdMicrometersByDefocus: [near.map((v) => v * .7), flat, far.map((v) => v * .7)], pupilThroughputByField: [1, .95, .85] }),
128
- tradeoffs: ["Lower matched-reference peripheral gain/noise amplification than Professional; not universally inferior."] },
129
- { tier: "professional", label: "Professional", presetId: "photivra-professional", presetVersion: version, scientificStatus: "approximation", evidence,
130
- body: bodyAssets("photivra-professional-body", 25600, 12, 24, { bitDepth: 14, blackLevelCode: 1024, saturationElectrons: 60000,
131
- maximumAnalogGain: 128, lowGainReadNoise: 2, highGainReadNoise: 1.1, highGainFromIso: 800, highGainMaximumCharge: 16000,
132
- prnu: .004, dsnu: .15, hotFraction: 5e-5, hotMultiplier: 30, rowRms: .15, columnRms: .1, instanceSeed: 0x6a09e667 }, .008, .85, .02, true, true),
133
- lens: lensAssets("photivra-professional-prime", { ...common, distortionK1: -.01, lateralCaK1Offset: .002, vignettingR2: -.35,
134
- breathingProjectionScale: 1.005, transmission: .9, correctionGainStrength: .8, ghostPowerFraction: .001, veilPowerFraction: .002,
135
- pupilAmplitudeByField: [disk, disk, disk], pupilOpdMicrometersByDefocus: [near.map((v) => v * .9), flat, far.map((v) => v * .6)], pupilThroughputByField: [1, .98, .95] }),
136
- tradeoffs: ["Less edge clipping/stray light, with greater f/4 falloff/gain cost than Prosumer and asymmetric near/far wavefront character."] }
137
- ];
129
+ function buildGenericTierAssets(version) {
130
+ return [
131
+ { tier: "consumer", label: "Consumer", presetId: "photivra-consumer", presetVersion: version, scientificStatus: "approximation", evidence,
132
+ body: bodyAssets(version, "photivra-consumer-body", 6400, 4, 8, { bitDepth: 12, blackLevelCode: 256, saturationElectrons: 20000,
133
+ maximumAnalogGain: 32, lowGainReadNoise: 6, highGainReadNoise: 2.5, highGainFromIso: 800, highGainMaximumCharge: 6000,
134
+ prnu: .01, dsnu: .3, hotFraction: 2e-4, hotMultiplier: 50, rowRms: .6, columnRms: .4, instanceSeed: 0x51ed270b }, .03, .35, .005, false, false),
135
+ lens: lensAssets(version, "photivra-consumer-prime", { ...common, distortionK1: -.06, lateralCaK1Offset: .008, vignettingR2: -.5,
136
+ breathingProjectionScale: 1.03, transmission: .75, correctionGainStrength: .8, ghostPowerFraction: .006, veilPowerFraction: .012,
137
+ pupilAmplitudeByField: [disk, clipped, clippedMore], pupilOpdMicrometersByDefocus: [near, flat, far], pupilThroughputByField: [1, .85, .65] }),
138
+ tradeoffs: ["Limited continuous AF; heavier digital correction and edge pupil clipping in matched reference."] },
139
+ { tier: "prosumer", label: "Prosumer", presetId: "photivra-prosumer", presetVersion: version, scientificStatus: "approximation", evidence,
140
+ body: bodyAssets(version, "photivra-prosumer-body", 12800, 8, 16, { bitDepth: 14, blackLevelCode: 1024, saturationElectrons: 40000,
141
+ maximumAnalogGain: 64, lowGainReadNoise: 3, highGainReadNoise: 1.4, highGainFromIso: 800, highGainMaximumCharge: 12000,
142
+ prnu: .006, dsnu: .2, hotFraction: 1e-4, hotMultiplier: 40, rowRms: .3, columnRms: .2, instanceSeed: 0x2c1b3c6d }, .015, .65, .01, true, true),
143
+ lens: lensAssets(version, "photivra-prosumer-prime", { ...common, distortionK1: -.025, lateralCaK1Offset: .004, vignettingR2: -.25,
144
+ breathingProjectionScale: 1.015, transmission: .85, correctionGainStrength: .6, ghostPowerFraction: .003, veilPowerFraction: .006,
145
+ pupilAmplitudeByField: [disk, disk, clipped], pupilOpdMicrometersByDefocus: [near.map((v) => v * .7), flat, far.map((v) => v * .7)], pupilThroughputByField: [1, .95, .85] }),
146
+ tradeoffs: ["Lower matched-reference peripheral gain/noise amplification than Professional; not universally inferior."] },
147
+ { tier: "professional", label: "Professional", presetId: "photivra-professional", presetVersion: version, scientificStatus: "approximation", evidence,
148
+ body: bodyAssets(version, "photivra-professional-body", 25600, 12, 24, { bitDepth: 14, blackLevelCode: 1024, saturationElectrons: 60000,
149
+ maximumAnalogGain: 128, lowGainReadNoise: 2, highGainReadNoise: 1.1, highGainFromIso: 800, highGainMaximumCharge: 16000,
150
+ prnu: .004, dsnu: .15, hotFraction: 5e-5, hotMultiplier: 30, rowRms: .15, columnRms: .1, instanceSeed: 0x6a09e667 }, .008, .85, .02, true, true),
151
+ lens: lensAssets(version, "photivra-professional-prime", { ...common, distortionK1: -.01, lateralCaK1Offset: .002, vignettingR2: -.35,
152
+ breathingProjectionScale: 1.005, transmission: .9, correctionGainStrength: .8, ghostPowerFraction: .001, veilPowerFraction: .002,
153
+ pupilAmplitudeByField: [disk, disk, disk], pupilOpdMicrometersByDefocus: [near.map((v) => v * .9), flat, far.map((v) => v * .6)], pupilThroughputByField: [1, .98, .95] }),
154
+ tradeoffs: ["Less edge clipping/stray light, with greater f/4 falloff/gain cost than Prosumer and asymmetric near/far wavefront character."] }
155
+ ];
156
+ }
157
+ /** The presets of the current version, 2.1.0 (third-stop ISO settings). */
158
+ export const GENERIC_TIER_ASSETS = buildGenericTierAssets("2.1.0");
159
+ let historical;
160
+ /** The presets of an exact version; 2.0.0 (whole-stop ISO) is built on first use. */
161
+ export function genericTierAssets(version) {
162
+ if (version === "2.1.0")
163
+ return GENERIC_TIER_ASSETS;
164
+ return historical ??= buildGenericTierAssets("2.0.0");
165
+ }
138
166
  //# sourceMappingURL=generic-tier-assets.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"generic-tier-assets.js","sourceRoot":"","sources":["../../src/equipment/generic-tier-assets.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Synthetic catalog data, owned by the project, for generic camera tiers. Bodies (capabilities and\n * readout) and lenses (optical and correction profiles) are defined separately.\n *\n * Choosing a tier changes explicit profile values. It never applies a universal quality multiplier.\n * The caller still supplies the CFA (colour filter array) and light-collection geometry and the\n * actual capture raster. The numbers are not measured calibration.\n * @see docs/RELEASE_1_0.md and the corresponding domain guide.\n */\n\nimport type { EvidenceBackedFact, EvidenceProvenance } from \"../core/evidence-provenance.js\";\nimport { parseGenericBodyExposureCapabilityProfile, parseGenericLensExposureCapabilityProfile,\n type GenericBodyExposureCapabilityProfile, type GenericLensExposureCapabilityProfile } from \"./exposure-capabilities.js\";\nimport { parseIsoCapabilityProfile, type IsoCapabilityProfile } from \"./iso-capabilities.js\";\nimport { parseGenericReleaseCapabilityProfile, type GenericReleaseCapabilityProfile } from \"./release-capabilities.js\";\nimport { parseFocusControlProfile, type FocusControlProfile } from \"../capture/focus-control.js\";\nimport { parseWhiteBalanceProfile, type WhiteBalanceProfile } from \"../color/white-balance.js\";\nimport { parseStabilizationSystemProfile, type StabilizationSystemProfile } from \"../stabilization/system.js\";\nimport { parseSensorReadoutConversionProfile, type SensorReadoutConversionProfile } from \"../sensor/raw-readout.js\";\nimport { parseGenericIsoSignalChainProfile, type GenericIsoSignalChainProfile } from \"../sensor/iso-signal-chain.js\";\nimport { parseExposureMeteringProfile, type ExposureMeteringProfile } from \"../exposure/metering.js\";\nimport { parseGenericBodyMeteringCapabilityProfile, type GenericBodyMeteringCapabilityProfile } from \"./metering-capabilities.js\";\nimport { parseFlashSyncCapabilityProfile, type FlashSyncCapabilityProfile } from \"../exposure/flash.js\";\nimport type { SensorReadoutTimingDeclaration } from \"../sensor/readout-timing.js\";\nimport { createIsoGainReadoutRegimes } from \"../sensor/iso-gain.js\";\nimport { parseSensorFixedPatternNoiseProfile, type SensorFixedPatternNoiseProfile } from \"../sensor/fixed-pattern-noise.js\";\n\nexport type GenericEquipmentTier = \"consumer\" | \"prosumer\" | \"professional\";\nexport interface GenericVersionedAsset<T> { assetId: string; assetVersion: string; profile: T }\nexport interface GenericTierBodyAssets {\n exposure: GenericBodyExposureCapabilityProfile;\n iso: IsoCapabilityProfile;\n signalChain: GenericIsoSignalChainProfile;\n readout: readonly GenericVersionedAsset<SensorReadoutConversionProfile>[];\n /** Global data readout (no skew across the frame). The default timing asset. */\n readoutTiming: GenericVersionedAsset<SensorReadoutTimingDeclaration>;\n /** Optional rolling readout variant, with an explicit top-to-bottom skew across the frame. */\n rollingReadoutTiming: GenericVersionedAsset<SensorReadoutTimingDeclaration>;\n /** Optional synthetic fixed-pattern noise for this body. Never applied unless a caller attaches it. */\n fixedPatternNoise: GenericVersionedAsset<SensorFixedPatternNoiseProfile>;\n release: GenericReleaseCapabilityProfile;\n focus: FocusControlProfile;\n stabilization: StabilizationSystemProfile;\n whiteBalance: WhiteBalanceProfile;\n metering: readonly GenericVersionedAsset<ExposureMeteringProfile>[];\n meteringCapabilities: GenericBodyMeteringCapabilityProfile;\n flashSync: FlashSyncCapabilityProfile;\n}\nexport interface GenericTierLensAssets {\n form: \"prime\";\n exposure: GenericLensExposureCapabilityProfile;\n /** Explicit synthetic coefficients, not measured calibration or a quality score. */\n matchedReference: {\n focalLengthMm: 50; aperture: 4; focusDistanceM: 5; wavelengthNm: 550;\n normalizationRadiusMm: number;\n distortionK1: number; lateralCaK1Offset: number; vignettingR2: number;\n breathingProjectionScale: number; transmission: number;\n correctionGainStrength: number; correctionCaFraction: number;\n ghostPowerFraction: number; veilPowerFraction: number;\n pupilAmplitudeByField: readonly (readonly number[])[];\n pupilOpdMicrometersByDefocus: readonly (readonly number[])[];\n pupilThroughputByField: readonly number[];\n };\n profileReferences: readonly { profileId: string; profileVersion: string }[];\n limitations: readonly string[];\n}\nexport interface GenericEquipmentTierPreset {\n tier: GenericEquipmentTier;\n label: \"Consumer\" | \"Prosumer\" | \"Professional\";\n presetId: string; presetVersion: \"2.0.0\";\n scientificStatus: \"approximation\";\n evidence: readonly EvidenceProvenance[];\n body: GenericTierBodyAssets;\n lens: GenericTierLensAssets;\n tradeoffs: readonly string[];\n}\n\nconst evidence: readonly EvidenceProvenance[] = [{ sourceOrigin: \"photivra\", sourceReference: \"photivra:generic-tier-assets-v1\",\n reuseStatus: \"photivra-owned\" }];\nconst limitations = [\"Synthetic educational design values; no named camera/lens calibration or population ranking.\"];\nconst fact = <T>(value: T): EvidenceBackedFact<T> => ({ value, evidence });\nconst version = \"2.0.0\";\nconst disk = [0,0,1,0,0, 0,1,1,1,0, 1,1,1,1,1, 0,1,1,1,0, 0,0,1,0,0];\nconst clipped = [0,0,1,0,0, 0,1,1,1,0, 0,1,1,1,1, 0,1,1,1,0, 0,0,1,0,0];\nconst clippedMore = [0,0,0,0,0, 0,0,1,1,0, 0,0,1,1,1, 0,0,1,1,0, 0,0,0,0,0];\nconst near = [0,0,.12,0,0, 0,.06,0,.06,0, .12,0,-.04,0,.12, 0,.06,0,.06,0, 0,0,.12,0,0];\nconst flat = Array<number>(25).fill(0);\nconst far = near.map((v) => -v);\n\n/**\n * Synthetic, educational sensor design values for each tier: ADC (analogue-to-digital converter),\n * saturation signal Q0 at base ISO, analogue gain range, read noise for each conversion-gain mode,\n * and fixed-pattern noise sizes. They are plausible orders of magnitude for consumer\n * interchangeable-lens sensors. They are not data from any real camera.\n */\ninterface SyntheticSensorDesign {\n bitDepth: number; blackLevelCode: number; saturationElectrons: number; maximumAnalogGain: number;\n lowGainReadNoise: number; highGainReadNoise: number; highGainFromIso: number; highGainMaximumCharge: number;\n prnu: number; dsnu: number; hotFraction: number; hotMultiplier: number; rowRms: number; columnRms: number; instanceSeed: number;\n}\n/** Used only to build data. Tier labels never enter any scientific equation. */\nfunction bodyAssets(id: string, isoMax: number, cadence: number, frames: number, sensor: SyntheticSensorDesign,\n dataReadoutSeconds: number, gain: number, maxAngle: number, continuousAf: boolean, advancedPolicies: boolean): GenericTierBodyAssets {\n const isoValues = [100, 200, 400, 800, 1600, 3200, 6400, 12800, 25600].filter((v) => v <= isoMax);\n const exposure = parseGenericBodyExposureCapabilityProfile({ schemaVersion: \"0.1.0\", profileId: id+\":exposure\", profileVersion: version,\n scientificStatus: \"approximation\", evidence, shutter: { durationSecondsRange: fact({ minimum: 1/8000, maximum: 30 }), settingGrid: { kind: \"continuous-within-range\" } },\n iso: { range: fact({ minimum: 100, maximum: isoMax }), settingGrid: { kind: \"discrete-values\", values: fact(isoValues) }, autoIso: fact(\"supported\") } });\n const iso = parseIsoCapabilityProfile({ schemaVersion: \"0.1.0\", profileId: id+\":iso\", profileVersion: version,\n capabilityMeaning: \"reported-exposure-index-capability-not-physical-gain\", standard: { exposureIndexRange: { minimum: 100, maximum: isoMax },\n settingGrid: { kind: \"discrete-values\", values: isoValues } }, expandedSettings: [], autoIso: { availability: \"supported\", standardExposureIndexRange: { minimum: 100, maximum: isoMax }, evidence },\n captureModePolicies: [], evidence });\n const isoGain = createIsoGainReadoutRegimes({ regimeIdPrefix: \"\", scientificStatus: \"approximation\", baseExposureIndex: 100,\n exposureIndices: isoValues, baseSaturationElectronEquivalent: fact(sensor.saturationElectrons), maximumAnalogGain: fact(sensor.maximumAnalogGain),\n adc: { bitDepth: sensor.bitDepth, blackLevelCode: sensor.blackLevelCode, digitalSaturationCode: 2**sensor.bitDepth-1 },\n conversionGainModes: [{ mode: \"low-conversion-gain\", minimumExposureIndex: 100, readNoiseRmsElectrons: fact(sensor.lowGainReadNoise) },\n { mode: \"high-conversion-gain\", minimumExposureIndex: sensor.highGainFromIso, readNoiseRmsElectrons: fact(sensor.highGainReadNoise),\n maximumChargeElectrons: fact(sensor.highGainMaximumCharge) }],\n evidence, limitations: [...limitations, \"ISO gain follows the declared base-ISO saturation signal and analog range; read noise per conversion-gain mode is a synthetic design value.\"] });\n const readout = [\"red\", \"green\", \"blue\"].map((channelId): GenericVersionedAsset<SensorReadoutConversionProfile> => ({ assetId: id+\":readout:\"+channelId, assetVersion: version,\n profile: parseSensorReadoutConversionProfile({ schemaVersion: \"0.1.0\", profileId: id+\":readout\", colorSamplingProfileId: \"photivra-generic-bayer\", channelId,\n regimeSelectionOwnedBy: \"explicit-upstream-camera-state-not-inferred-from-iso\", evidence, regimes: isoGain.regimes }) }));\n const signalChain = parseGenericIsoSignalChainProfile({ schemaVersion: \"0.1.0\", profileId: id+\":signal-chain\", profileVersion: version,\n scientificStatus: \"approximation\", isoCapabilityProfileId: iso.profileId, readoutProfileId: id+\":readout\",\n behaviorMeaning: \"iso-state-selects-explicit-readout-regime-not-noise-equation\", captureModeBindings: [{ captureModeId: \"native-still\",\n standardRegimeBands: isoGain.standardRegimeBands, expandedRegimeBindings: [], evidence }],\n photonShotNoiseOwnedUpstream: true, processedImageBehaviorIncluded: false, fixedPatternNoiseModeled: false, lowSignalColorDegradationModeled: false,\n evidence, limitations });\n const release = parseGenericReleaseCapabilityProfile({ schemaVersion: \"0.1.0\", profileId: id+\":release\", profileVersion: version,\n scientificStatus: \"approximation\", evidence, supportedDriveModes: fact([\"single\", \"burst\", \"self-timer\"]), maximumLogicalFramesPerSequence: fact(frames),\n maximumCadenceFps: fact(cadence), minimumInterFrameGapSeconds: fact(0), overlappingOrdinaryStillExposures: false,\n exposureBracketing: { availability: fact(\"supported\"), supportedAxes: [\"shutter\", \"iso\"] }, focusBracketing: { availability: fact(\"unsupported\") } });\n const focus = parseFocusControlProfile({ schemaVersion: \"0.1.0\", profileId: id+\":focus\", profileVersion: version, scientificStatus: \"approximation\",\n supportedModes: continuousAf ? [\"manual\", \"single-af\", \"continuous-af\"] : [\"manual\", \"single-af\"], actuator: { kind: \"ideal-instantaneous\", evidence },\n continuousTargetLossPolicy: \"hold-last-focus-require-explicit-reacquisition\", supportedReleasePriorities: [\"focus-priority\", \"release-priority\", \"balanced\"],\n evidence, limitations: [...limitations, \"AF actuator speed and subject recognition are not tier performance claims.\"] });\n const stabilization = parseStabilizationSystemProfile({ schemaVersion: \"0.1.0\", profileId: id+\":stabilization\", profileVersion: version,\n profileKind: \"generic-synthetic\", scientificStatus: \"approximation\", architecture: \"sensor-shift\", captureKind: \"still\",\n axisResponses: [\"pitch\", \"yaw\", \"roll\"].map((axis) => ({ axis, correctionGain: fact(gain), latencySeconds: fact(.001), maximumCorrectionAngleRad: fact(maxAngle) })),\n panningPolicy: { kind: \"none\" }, controlTransientModeled: false, spontaneousDriftModeled: false, cameraTranslationCorrectionModeled: false,\n digitalStabilizationIncluded: false, supportPolicyIncluded: false, stopRatingUsedAsDynamicResponse: false, evidence, limitations });\n const whiteBalance = parseWhiteBalanceProfile({ schemaVersion: \"0.1.0\", profileId: id+\":white-balance\", profileVersion: version,\n scientificStatus: \"approximation\", inputDomain: \"relative-pre-wb-camera-linear-rgb\", presets: [{ presetId: \"neutral\", label: \"Neutral reference\",\n channelGains: fact({ red: 1, green: 1, blue: 1 }) }], awbPolicies: [\n { policyId: \"neutral-priority\", intent: \"neutral-priority\", correctionStrength: fact(1) },\n ...(advancedPolicies ? [{ policyId: \"ambience\", intent: \"ambience-preserving\", correctionStrength: fact(.5) }] : [])], evidence, limitations });\n const metering = [{ kind: \"multi-zone-uniform\" }, ...(advancedPolicies ? [{ kind: \"highlight-weighted\", minimumWeightFraction: .2, exponent: 2 }] : [])]\n .map((policy): GenericVersionedAsset<ExposureMeteringProfile> => ({ assetId: id+\":meter:\"+policy.kind, assetVersion: version,\n profile: parseExposureMeteringProfile({ schemaVersion: \"0.1.0\", profileId: id+\":meter:\"+policy.kind, scientificStatus: \"approximation\",\n inputDomain: \"relative-pre-exposure-linear-signal\", captureRegion: \"oriented-active-capture\", policy,\n target: { kind: \"relative-signal-reference\", targetRelativeSignal: .18, evidence }, evidence,\n limitations: [...limitations, \"0.18 is a declared target policy, not universal scene/camera truth.\"] }) }));\n const meteringCapabilities = parseGenericBodyMeteringCapabilityProfile({ schemaVersion: \"0.1.0\", profileId: id+\":metering-capabilities\", profileVersion: version,\n scientificStatus: \"approximation\", evidence, supportedMeteringProfiles: metering.map((m) => ({ meteringProfileId: m.profile.profileId, policyKind: m.profile.policy.kind, evidence })),\n spotFocusPointLinkage: { availability: \"unsupported\", evidence } });\n const timingId = id+\":data-readout\";\n const fixedPatternNoise = parseSensorFixedPatternNoiseProfile({ schemaVersion: \"0.1.0\", profileId: id+\":fixed-pattern\",\n colorSamplingProfileId: \"photivra-generic-bayer\", scientificStatus: \"approximation\", sensorInstanceSeedUint32: sensor.instanceSeed,\n photoResponseNonUniformity: { relativeStandardDeviation: fact(sensor.prnu) }, darkSignalNonUniformity: { relativeStandardDeviation: fact(sensor.dsnu) },\n hotPixels: { siteFraction: fact(sensor.hotFraction), darkCurrentMultiplier: fact(sensor.hotMultiplier) },\n rowOffset: { rmsElectrons: fact(sensor.rowRms) }, columnOffset: { rmsElectrons: fact(sensor.columnRms) },\n patternDistribution: \"normal-factors-truncated-at-zero\", evidence,\n limitations: [...limitations, \"Synthetic fixed-pattern magnitudes for teaching; opt-in only and not a measured sensor population.\"] });\n return { exposure, iso, signalChain, readout, release, focus, stabilization, whiteBalance, metering, meteringCapabilities,\n readoutTiming: { assetId: timingId, assetVersion: version, profile: { readoutMode: \"global\", captureReadoutDurationSeconds: {\n value: dataReadoutSeconds, unit: \"s\", evidence } } },\n rollingReadoutTiming: { assetId: id+\":rolling-data-readout\", assetVersion: version, profile: { readoutMode: \"rolling\",\n captureReadoutDurationSeconds: { value: dataReadoutSeconds, unit: \"s\", evidence }, scanDirectionNative: fact(\"top-to-bottom\"),\n spatialSamplingSkewSeconds: { value: dataReadoutSeconds, unit: \"s\", evidence } } },\n fixedPatternNoise: { assetId: id+\":fixed-pattern\", assetVersion: version, profile: fixedPatternNoise },\n flashSync: parseFlashSyncCapabilityProfile({ schemaVersion: \"0.1.0\", profileId: id+\":flash-sync\", profileVersion: version,\n captureModeId: \"native-still\", timingProfileId: timingId, supportedOrdinarySyncModes: [\"front-curtain\", \"rear-curtain\"],\n highSpeedSyncSupported: false, ordinarySyncRequiresWholeActiveFrameSimultaneouslyExposed: true, evidence, limitations }) };\n}\nfunction lensAssets(id: string, r: GenericTierLensAssets[\"matchedReference\"]): GenericTierLensAssets {\n return { form: \"prime\", exposure: parseGenericLensExposureCapabilityProfile({ schemaVersion: \"0.1.0\", profileId: id+\":exposure\", profileVersion: version,\n scientificStatus: \"approximation\", evidence, focalLengthMmRange: fact({ minimum: 50, maximum: 50 }), aperture: { widestAvailableFNumber: {\n kind: \"constant\", fNumber: fact(4) }, narrowestAvailableFNumber: fact(16), settingGrid: { kind: \"continuous-within-range\" } } }),\n matchedReference: r, profileReferences: [\"radial\", \"lateral-ca\", \"vignetting\", \"breathing\", \"transmission\", \"pupil\", \"stray\", \"correction\"]\n .map((role) => ({ profileId: id+\":\"+role, profileVersion: version })),\n limitations: [...limitations, \"Optical reference response is limited to 50 mm, f/4, focus 5 m and explicit field/defocus/wavelength slices; capabilities do not authorize extrapolation.\",\n \"The initial prime has no OIS; body stabilization is separate.\"] };\n}\nconst common = { focalLengthMm: 50 as const, aperture: 4 as const, focusDistanceM: 5 as const, wavelengthNm: 550 as const,\n normalizationRadiusMm: Math.hypot(18,12), correctionCaFraction: .8 };\nexport const GENERIC_TIER_ASSETS: readonly GenericEquipmentTierPreset[] = [\n { tier: \"consumer\", label: \"Consumer\", presetId: \"photivra-consumer\", presetVersion: version, scientificStatus: \"approximation\", evidence,\n body: bodyAssets(\"photivra-consumer-body\", 6400, 4, 8, { bitDepth: 12, blackLevelCode: 256, saturationElectrons: 20000,\n maximumAnalogGain: 32, lowGainReadNoise: 6, highGainReadNoise: 2.5, highGainFromIso: 800, highGainMaximumCharge: 6000,\n prnu: .01, dsnu: .3, hotFraction: 2e-4, hotMultiplier: 50, rowRms: .6, columnRms: .4, instanceSeed: 0x51ed270b }, .03, .35, .005, false, false),\n lens: lensAssets(\"photivra-consumer-prime\", { ...common, distortionK1: -.06, lateralCaK1Offset: .008, vignettingR2: -.5,\n breathingProjectionScale: 1.03, transmission: .75, correctionGainStrength: .8, ghostPowerFraction: .006, veilPowerFraction: .012,\n pupilAmplitudeByField: [disk, clipped, clippedMore], pupilOpdMicrometersByDefocus: [near, flat, far], pupilThroughputByField: [1,.85,.65] }),\n tradeoffs: [\"Limited continuous AF; heavier digital correction and edge pupil clipping in matched reference.\"] },\n { tier: \"prosumer\", label: \"Prosumer\", presetId: \"photivra-prosumer\", presetVersion: version, scientificStatus: \"approximation\", evidence,\n body: bodyAssets(\"photivra-prosumer-body\", 12800, 8, 16, { bitDepth: 14, blackLevelCode: 1024, saturationElectrons: 40000,\n maximumAnalogGain: 64, lowGainReadNoise: 3, highGainReadNoise: 1.4, highGainFromIso: 800, highGainMaximumCharge: 12000,\n prnu: .006, dsnu: .2, hotFraction: 1e-4, hotMultiplier: 40, rowRms: .3, columnRms: .2, instanceSeed: 0x2c1b3c6d }, .015, .65, .01, true, true),\n lens: lensAssets(\"photivra-prosumer-prime\", { ...common, distortionK1: -.025, lateralCaK1Offset: .004, vignettingR2: -.25,\n breathingProjectionScale: 1.015, transmission: .85, correctionGainStrength: .6, ghostPowerFraction: .003, veilPowerFraction: .006,\n pupilAmplitudeByField: [disk, disk, clipped], pupilOpdMicrometersByDefocus: [near.map((v)=>v*.7), flat, far.map((v)=>v*.7)], pupilThroughputByField: [1,.95,.85] }),\n tradeoffs: [\"Lower matched-reference peripheral gain/noise amplification than Professional; not universally inferior.\"] },\n { tier: \"professional\", label: \"Professional\", presetId: \"photivra-professional\", presetVersion: version, scientificStatus: \"approximation\", evidence,\n body: bodyAssets(\"photivra-professional-body\", 25600, 12, 24, { bitDepth: 14, blackLevelCode: 1024, saturationElectrons: 60000,\n maximumAnalogGain: 128, lowGainReadNoise: 2, highGainReadNoise: 1.1, highGainFromIso: 800, highGainMaximumCharge: 16000,\n prnu: .004, dsnu: .15, hotFraction: 5e-5, hotMultiplier: 30, rowRms: .15, columnRms: .1, instanceSeed: 0x6a09e667 }, .008, .85, .02, true, true),\n lens: lensAssets(\"photivra-professional-prime\", { ...common, distortionK1: -.01, lateralCaK1Offset: .002, vignettingR2: -.35,\n breathingProjectionScale: 1.005, transmission: .9, correctionGainStrength: .8, ghostPowerFraction: .001, veilPowerFraction: .002,\n pupilAmplitudeByField: [disk, disk, disk], pupilOpdMicrometersByDefocus: [near.map((v)=>v*.9), flat, far.map((v)=>v*.6)], pupilThroughputByField: [1,.98,.95] }),\n tradeoffs: [\"Less edge clipping/stray light, with greater f/4 falloff/gain cost than Prosumer and asymmetric near/far wavefront character.\"] }\n];\n"]}
1
+ {"version":3,"file":"generic-tier-assets.js","sourceRoot":"","sources":["../../src/equipment/generic-tier-assets.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Synthetic catalog data, owned by the project, for generic camera tiers. Bodies (capabilities and\n * readout) and lenses (optical and correction profiles) are defined separately.\n *\n * Choosing a tier changes explicit profile values. It never applies a universal quality multiplier.\n * The caller still supplies the CFA (colour filter array) and light-collection geometry and the\n * actual capture raster. The numbers are not measured calibration.\n * @see docs/RELEASE_1_0.md and the corresponding domain guide.\n */\n\nimport type { EvidenceBackedFact, EvidenceProvenance } from \"../core/evidence-provenance.js\";\nimport { parseGenericBodyExposureCapabilityProfile, parseGenericLensExposureCapabilityProfile,\n type GenericBodyExposureCapabilityProfile, type GenericLensExposureCapabilityProfile } from \"./exposure-capabilities.js\";\nimport { parseIsoCapabilityProfile, type IsoCapabilityProfile } from \"./iso-capabilities.js\";\nimport { parseGenericReleaseCapabilityProfile, type GenericReleaseCapabilityProfile } from \"./release-capabilities.js\";\nimport { parseFocusControlProfile, type FocusControlProfile } from \"../capture/focus-control.js\";\nimport { parseWhiteBalanceProfile, type WhiteBalanceProfile } from \"../color/white-balance.js\";\nimport { parseStabilizationSystemProfile, type StabilizationSystemProfile } from \"../stabilization/system.js\";\nimport { parseSensorReadoutConversionProfile, type SensorReadoutConversionProfile } from \"../sensor/raw-readout.js\";\nimport { parseGenericIsoSignalChainProfile, type GenericIsoSignalChainProfile } from \"../sensor/iso-signal-chain.js\";\nimport { parseExposureMeteringProfile, type ExposureMeteringProfile } from \"../exposure/metering.js\";\nimport { parseGenericBodyMeteringCapabilityProfile, type GenericBodyMeteringCapabilityProfile } from \"./metering-capabilities.js\";\nimport { parseFlashSyncCapabilityProfile, type FlashSyncCapabilityProfile } from \"../exposure/flash.js\";\nimport type { SensorReadoutTimingDeclaration } from \"../sensor/readout-timing.js\";\nimport { createIsoGainReadoutRegimes } from \"../sensor/iso-gain.js\";\nimport { parseSensorFixedPatternNoiseProfile, type SensorFixedPatternNoiseProfile } from \"../sensor/fixed-pattern-noise.js\";\n\nexport type GenericEquipmentTier = \"consumer\" | \"prosumer\" | \"professional\";\nexport interface GenericVersionedAsset<T> { assetId: string; assetVersion: string; profile: T }\nexport interface GenericTierBodyAssets {\n exposure: GenericBodyExposureCapabilityProfile;\n iso: IsoCapabilityProfile;\n signalChain: GenericIsoSignalChainProfile;\n readout: readonly GenericVersionedAsset<SensorReadoutConversionProfile>[];\n /** Global data readout (no skew across the frame). The default timing asset. */\n readoutTiming: GenericVersionedAsset<SensorReadoutTimingDeclaration>;\n /** Optional rolling readout variant, with an explicit top-to-bottom skew across the frame. */\n rollingReadoutTiming: GenericVersionedAsset<SensorReadoutTimingDeclaration>;\n /** Optional synthetic fixed-pattern noise for this body. Never applied unless a caller attaches it. */\n fixedPatternNoise: GenericVersionedAsset<SensorFixedPatternNoiseProfile>;\n release: GenericReleaseCapabilityProfile;\n focus: FocusControlProfile;\n stabilization: StabilizationSystemProfile;\n whiteBalance: WhiteBalanceProfile;\n metering: readonly GenericVersionedAsset<ExposureMeteringProfile>[];\n meteringCapabilities: GenericBodyMeteringCapabilityProfile;\n flashSync: FlashSyncCapabilityProfile;\n}\nexport interface GenericTierLensAssets {\n form: \"prime\";\n exposure: GenericLensExposureCapabilityProfile;\n /** Explicit synthetic coefficients, not measured calibration or a quality score. */\n matchedReference: {\n focalLengthMm: 50; aperture: 4; focusDistanceM: 5; wavelengthNm: 550;\n normalizationRadiusMm: number;\n distortionK1: number; lateralCaK1Offset: number; vignettingR2: number;\n breathingProjectionScale: number; transmission: number;\n correctionGainStrength: number; correctionCaFraction: number;\n ghostPowerFraction: number; veilPowerFraction: number;\n pupilAmplitudeByField: readonly (readonly number[])[];\n pupilOpdMicrometersByDefocus: readonly (readonly number[])[];\n pupilThroughputByField: readonly number[];\n };\n profileReferences: readonly { profileId: string; profileVersion: string }[];\n limitations: readonly string[];\n}\nexport interface GenericEquipmentTierPreset {\n tier: GenericEquipmentTier;\n label: \"Consumer\" | \"Prosumer\" | \"Professional\";\n presetId: string; presetVersion: GenericTierPresetVersion;\n scientificStatus: \"approximation\";\n evidence: readonly EvidenceProvenance[];\n body: GenericTierBodyAssets;\n lens: GenericTierLensAssets;\n tradeoffs: readonly string[];\n}\n\nconst evidence: readonly EvidenceProvenance[] = [{ sourceOrigin: \"photivra\", sourceReference: \"photivra:generic-tier-assets-v1\",\n reuseStatus: \"photivra-owned\" }];\nconst limitations = [\"Synthetic educational design values; no named camera/lens calibration or population ranking.\"];\nconst fact = <T>(value: T): EvidenceBackedFact<T> => ({ value, evidence });\n/**\n * The exact versions of the generic tier presets (no \"latest\" alias). 2.1.0 (2.14, round 5) adds the third-stop ISO\n * settings; 2.0.0 is kept, whole-stop, so saved selections and records of it still resolve to exactly what they named.\n */\nexport type GenericTierPresetVersion = \"2.0.0\" | \"2.1.0\";\n/** Whole-stop ISO settings of the 2.0.0 bodies (each body's list stops at its maximum). */\nexport const GENERIC_WHOLE_STOP_ISO_SETTINGS = /* @__PURE__ */ Object.freeze([100, 200, 400, 800, 1600, 3200, 6400, 12800, 25600] as const);\n/**\n * Third-stop ISO settings of the 2.1.0 bodies: the conventional rounded markings of S = 100·2^(k/3), k = 0 … 24 (125 for\n * 126.0, 160 for 158.7 …; each within 2 % of the exact value). The engine takes the setting as the exact ISO speed.\n */\n/**\n * The standard third-stop shutter times, seconds, from 1/8000 s to 30 s: the conventional markings of t = 2^(k/3) s\n * (1/8000 for 2^−13, 1/6 for 2^−8/3, 0.3 for 2^−5/3, 30 for 2^5; each within 7 % of the exact value). The generic bodies'\n * shutters are continuous over 1/8000–30 s and take any time as exact, so these are the values to offer in a third-stop\n * dial, not a restriction.\n */\nexport const GENERIC_THIRD_STOP_SHUTTER_SECONDS = /* @__PURE__ */ Object.freeze([1 / 8000, 1 / 6400, 1 / 5000, 1 / 4000, 1 / 3200, 1 / 2500, 1 / 2000,\n 1 / 1600, 1 / 1250, 1 / 1000, 1 / 800, 1 / 640, 1 / 500, 1 / 400, 1 / 320, 1 / 250, 1 / 200, 1 / 160, 1 / 125, 1 / 100, 1 / 80, 1 / 60, 1 / 50, 1 / 40,\n 1 / 30, 1 / 25, 1 / 20, 1 / 15, 1 / 13, 1 / 10, 1 / 8, 1 / 6, 1 / 5, 1 / 4, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.3, 1.6, 2, 2.5, 3.2, 4, 5, 6, 8, 10, 13,\n 15, 20, 25, 30] as const);\nexport const GENERIC_THIRD_STOP_ISO_SETTINGS = /* @__PURE__ */ Object.freeze([100, 125, 160, 200, 250, 320, 400, 500, 640, 800, 1000, 1250, 1600,\n 2000, 2500, 3200, 4000, 5000, 6400, 8000, 10000, 12800, 16000, 20000, 25600] as const);\nconst disk = [0,0,1,0,0, 0,1,1,1,0, 1,1,1,1,1, 0,1,1,1,0, 0,0,1,0,0];\nconst clipped = [0,0,1,0,0, 0,1,1,1,0, 0,1,1,1,1, 0,1,1,1,0, 0,0,1,0,0];\nconst clippedMore = [0,0,0,0,0, 0,0,1,1,0, 0,0,1,1,1, 0,0,1,1,0, 0,0,0,0,0];\nconst near = [0,0,.12,0,0, 0,.06,0,.06,0, .12,0,-.04,0,.12, 0,.06,0,.06,0, 0,0,.12,0,0];\nconst flat = Array<number>(25).fill(0);\nconst far = near.map((v) => -v);\n\n/**\n * Synthetic, educational sensor design values for each tier: ADC (analogue-to-digital converter),\n * saturation signal Q0 at base ISO, analogue gain range, read noise for each conversion-gain mode,\n * and fixed-pattern noise sizes. They are plausible orders of magnitude for consumer\n * interchangeable-lens sensors. They are not data from any real camera.\n */\ninterface SyntheticSensorDesign {\n bitDepth: number; blackLevelCode: number; saturationElectrons: number; maximumAnalogGain: number;\n lowGainReadNoise: number; highGainReadNoise: number; highGainFromIso: number; highGainMaximumCharge: number;\n prnu: number; dsnu: number; hotFraction: number; hotMultiplier: number; rowRms: number; columnRms: number; instanceSeed: number;\n}\n/** Used only to build data. Tier labels never enter any scientific equation. */\nfunction bodyAssets(version: GenericTierPresetVersion, id: string, isoMax: number, cadence: number, frames: number, sensor: SyntheticSensorDesign,\n dataReadoutSeconds: number, gain: number, maxAngle: number, continuousAf: boolean, advancedPolicies: boolean): GenericTierBodyAssets {\n const isoValues: number[] = (version === \"2.0.0\" ? GENERIC_WHOLE_STOP_ISO_SETTINGS : GENERIC_THIRD_STOP_ISO_SETTINGS).filter((v) => v <= isoMax);\n const exposure = parseGenericBodyExposureCapabilityProfile({ schemaVersion: \"0.1.0\", profileId: id+\":exposure\", profileVersion: version,\n scientificStatus: \"approximation\", evidence, shutter: { durationSecondsRange: fact({ minimum: 1/8000, maximum: 30 }), settingGrid: { kind: \"continuous-within-range\" } },\n iso: { range: fact({ minimum: 100, maximum: isoMax }), settingGrid: { kind: \"discrete-values\", values: fact(isoValues) }, autoIso: fact(\"supported\") } });\n const iso = parseIsoCapabilityProfile({ schemaVersion: \"0.1.0\", profileId: id+\":iso\", profileVersion: version,\n capabilityMeaning: \"reported-exposure-index-capability-not-physical-gain\", standard: { exposureIndexRange: { minimum: 100, maximum: isoMax },\n settingGrid: { kind: \"discrete-values\", values: isoValues } }, expandedSettings: [], autoIso: { availability: \"supported\", standardExposureIndexRange: { minimum: 100, maximum: isoMax }, evidence },\n captureModePolicies: [], evidence });\n const isoGain = createIsoGainReadoutRegimes({ regimeIdPrefix: \"\", scientificStatus: \"approximation\", baseExposureIndex: 100,\n exposureIndices: isoValues, baseSaturationElectronEquivalent: fact(sensor.saturationElectrons), maximumAnalogGain: fact(sensor.maximumAnalogGain),\n adc: { bitDepth: sensor.bitDepth, blackLevelCode: sensor.blackLevelCode, digitalSaturationCode: 2**sensor.bitDepth-1 },\n conversionGainModes: [{ mode: \"low-conversion-gain\", minimumExposureIndex: 100, readNoiseRmsElectrons: fact(sensor.lowGainReadNoise) },\n { mode: \"high-conversion-gain\", minimumExposureIndex: sensor.highGainFromIso, readNoiseRmsElectrons: fact(sensor.highGainReadNoise),\n maximumChargeElectrons: fact(sensor.highGainMaximumCharge) }],\n evidence, limitations: [...limitations, \"ISO gain follows the declared base-ISO saturation signal and analog range; read noise per conversion-gain mode is a synthetic design value.\"] });\n const readout = [\"red\", \"green\", \"blue\"].map((channelId): GenericVersionedAsset<SensorReadoutConversionProfile> => ({ assetId: id+\":readout:\"+channelId, assetVersion: version,\n profile: parseSensorReadoutConversionProfile({ schemaVersion: \"0.1.0\", profileId: id+\":readout\", colorSamplingProfileId: \"photivra-generic-bayer\", channelId,\n regimeSelectionOwnedBy: \"explicit-upstream-camera-state-not-inferred-from-iso\", evidence, regimes: isoGain.regimes }) }));\n const signalChain = parseGenericIsoSignalChainProfile({ schemaVersion: \"0.1.0\", profileId: id+\":signal-chain\", profileVersion: version,\n scientificStatus: \"approximation\", isoCapabilityProfileId: iso.profileId, readoutProfileId: id+\":readout\",\n behaviorMeaning: \"iso-state-selects-explicit-readout-regime-not-noise-equation\", captureModeBindings: [{ captureModeId: \"native-still\",\n standardRegimeBands: isoGain.standardRegimeBands, expandedRegimeBindings: [], evidence }],\n photonShotNoiseOwnedUpstream: true, processedImageBehaviorIncluded: false, fixedPatternNoiseModeled: false, lowSignalColorDegradationModeled: false,\n evidence, limitations });\n const release = parseGenericReleaseCapabilityProfile({ schemaVersion: \"0.1.0\", profileId: id+\":release\", profileVersion: version,\n scientificStatus: \"approximation\", evidence, supportedDriveModes: fact([\"single\", \"burst\", \"self-timer\"]), maximumLogicalFramesPerSequence: fact(frames),\n maximumCadenceFps: fact(cadence), minimumInterFrameGapSeconds: fact(0), overlappingOrdinaryStillExposures: false,\n exposureBracketing: { availability: fact(\"supported\"), supportedAxes: [\"shutter\", \"iso\"] }, focusBracketing: { availability: fact(\"unsupported\") } });\n const focus = parseFocusControlProfile({ schemaVersion: \"0.1.0\", profileId: id+\":focus\", profileVersion: version, scientificStatus: \"approximation\",\n supportedModes: continuousAf ? [\"manual\", \"single-af\", \"continuous-af\"] : [\"manual\", \"single-af\"], actuator: { kind: \"ideal-instantaneous\", evidence },\n continuousTargetLossPolicy: \"hold-last-focus-require-explicit-reacquisition\", supportedReleasePriorities: [\"focus-priority\", \"release-priority\", \"balanced\"],\n evidence, limitations: [...limitations, \"AF actuator speed and subject recognition are not tier performance claims.\"] });\n const stabilization = parseStabilizationSystemProfile({ schemaVersion: \"0.1.0\", profileId: id+\":stabilization\", profileVersion: version,\n profileKind: \"generic-synthetic\", scientificStatus: \"approximation\", architecture: \"sensor-shift\", captureKind: \"still\",\n axisResponses: [\"pitch\", \"yaw\", \"roll\"].map((axis) => ({ axis, correctionGain: fact(gain), latencySeconds: fact(.001), maximumCorrectionAngleRad: fact(maxAngle) })),\n panningPolicy: { kind: \"none\" }, controlTransientModeled: false, spontaneousDriftModeled: false, cameraTranslationCorrectionModeled: false,\n digitalStabilizationIncluded: false, supportPolicyIncluded: false, stopRatingUsedAsDynamicResponse: false, evidence, limitations });\n const whiteBalance = parseWhiteBalanceProfile({ schemaVersion: \"0.1.0\", profileId: id+\":white-balance\", profileVersion: version,\n scientificStatus: \"approximation\", inputDomain: \"relative-pre-wb-camera-linear-rgb\", presets: [{ presetId: \"neutral\", label: \"Neutral reference\",\n channelGains: fact({ red: 1, green: 1, blue: 1 }) }], awbPolicies: [\n { policyId: \"neutral-priority\", intent: \"neutral-priority\", correctionStrength: fact(1) },\n ...(advancedPolicies ? [{ policyId: \"ambience\", intent: \"ambience-preserving\", correctionStrength: fact(.5) }] : [])], evidence, limitations });\n const metering = [{ kind: \"multi-zone-uniform\" }, ...(advancedPolicies ? [{ kind: \"highlight-weighted\", minimumWeightFraction: .2, exponent: 2 }] : [])]\n .map((policy): GenericVersionedAsset<ExposureMeteringProfile> => ({ assetId: id+\":meter:\"+policy.kind, assetVersion: version,\n profile: parseExposureMeteringProfile({ schemaVersion: \"0.1.0\", profileId: id+\":meter:\"+policy.kind, scientificStatus: \"approximation\",\n inputDomain: \"relative-pre-exposure-linear-signal\", captureRegion: \"oriented-active-capture\", policy,\n target: { kind: \"relative-signal-reference\", targetRelativeSignal: .18, evidence }, evidence,\n limitations: [...limitations, \"0.18 is a declared target policy, not universal scene/camera truth.\"] }) }));\n const meteringCapabilities = parseGenericBodyMeteringCapabilityProfile({ schemaVersion: \"0.1.0\", profileId: id+\":metering-capabilities\", profileVersion: version,\n scientificStatus: \"approximation\", evidence, supportedMeteringProfiles: metering.map((m) => ({ meteringProfileId: m.profile.profileId, policyKind: m.profile.policy.kind, evidence })),\n spotFocusPointLinkage: { availability: \"unsupported\", evidence } });\n const timingId = id+\":data-readout\";\n const fixedPatternNoise = parseSensorFixedPatternNoiseProfile({ schemaVersion: \"0.1.0\", profileId: id+\":fixed-pattern\",\n colorSamplingProfileId: \"photivra-generic-bayer\", scientificStatus: \"approximation\", sensorInstanceSeedUint32: sensor.instanceSeed,\n photoResponseNonUniformity: { relativeStandardDeviation: fact(sensor.prnu) }, darkSignalNonUniformity: { relativeStandardDeviation: fact(sensor.dsnu) },\n hotPixels: { siteFraction: fact(sensor.hotFraction), darkCurrentMultiplier: fact(sensor.hotMultiplier) },\n rowOffset: { rmsElectrons: fact(sensor.rowRms) }, columnOffset: { rmsElectrons: fact(sensor.columnRms) },\n patternDistribution: \"normal-factors-truncated-at-zero\", evidence,\n limitations: [...limitations, \"Synthetic fixed-pattern magnitudes for teaching; opt-in only and not a measured sensor population.\"] });\n return { exposure, iso, signalChain, readout, release, focus, stabilization, whiteBalance, metering, meteringCapabilities,\n readoutTiming: { assetId: timingId, assetVersion: version, profile: { readoutMode: \"global\", captureReadoutDurationSeconds: {\n value: dataReadoutSeconds, unit: \"s\", evidence } } },\n rollingReadoutTiming: { assetId: id+\":rolling-data-readout\", assetVersion: version, profile: { readoutMode: \"rolling\",\n captureReadoutDurationSeconds: { value: dataReadoutSeconds, unit: \"s\", evidence }, scanDirectionNative: fact(\"top-to-bottom\"),\n spatialSamplingSkewSeconds: { value: dataReadoutSeconds, unit: \"s\", evidence } } },\n fixedPatternNoise: { assetId: id+\":fixed-pattern\", assetVersion: version, profile: fixedPatternNoise },\n flashSync: parseFlashSyncCapabilityProfile({ schemaVersion: \"0.1.0\", profileId: id+\":flash-sync\", profileVersion: version,\n captureModeId: \"native-still\", timingProfileId: timingId, supportedOrdinarySyncModes: [\"front-curtain\", \"rear-curtain\"],\n highSpeedSyncSupported: false, ordinarySyncRequiresWholeActiveFrameSimultaneouslyExposed: true, evidence, limitations }) };\n}\nfunction lensAssets(version: GenericTierPresetVersion, id: string, r: GenericTierLensAssets[\"matchedReference\"]): GenericTierLensAssets {\n return { form: \"prime\", exposure: parseGenericLensExposureCapabilityProfile({ schemaVersion: \"0.1.0\", profileId: id+\":exposure\", profileVersion: version,\n scientificStatus: \"approximation\", evidence, focalLengthMmRange: fact({ minimum: 50, maximum: 50 }), aperture: { widestAvailableFNumber: {\n kind: \"constant\", fNumber: fact(4) }, narrowestAvailableFNumber: fact(16), settingGrid: { kind: \"continuous-within-range\" } } }),\n matchedReference: r, profileReferences: [\"radial\", \"lateral-ca\", \"vignetting\", \"breathing\", \"transmission\", \"pupil\", \"stray\", \"correction\"]\n .map((role) => ({ profileId: id+\":\"+role, profileVersion: version })),\n limitations: [...limitations, \"Optical reference response is limited to 50 mm, f/4, focus 5 m and explicit field/defocus/wavelength slices; capabilities do not authorize extrapolation.\",\n \"The initial prime has no OIS; body stabilization is separate.\"] };\n}\nconst common = { focalLengthMm: 50 as const, aperture: 4 as const, focusDistanceM: 5 as const, wavelengthNm: 550 as const,\n normalizationRadiusMm: Math.hypot(18,12), correctionCaFraction: .8 };\nfunction buildGenericTierAssets(version: GenericTierPresetVersion): readonly GenericEquipmentTierPreset[] {\n return [\n { tier: \"consumer\", label: \"Consumer\", presetId: \"photivra-consumer\", presetVersion: version, scientificStatus: \"approximation\", evidence,\n body: bodyAssets(version, \"photivra-consumer-body\", 6400, 4, 8, { bitDepth: 12, blackLevelCode: 256, saturationElectrons: 20000,\n maximumAnalogGain: 32, lowGainReadNoise: 6, highGainReadNoise: 2.5, highGainFromIso: 800, highGainMaximumCharge: 6000,\n prnu: .01, dsnu: .3, hotFraction: 2e-4, hotMultiplier: 50, rowRms: .6, columnRms: .4, instanceSeed: 0x51ed270b }, .03, .35, .005, false, false),\n lens: lensAssets(version, \"photivra-consumer-prime\", { ...common, distortionK1: -.06, lateralCaK1Offset: .008, vignettingR2: -.5,\n breathingProjectionScale: 1.03, transmission: .75, correctionGainStrength: .8, ghostPowerFraction: .006, veilPowerFraction: .012,\n pupilAmplitudeByField: [disk, clipped, clippedMore], pupilOpdMicrometersByDefocus: [near, flat, far], pupilThroughputByField: [1,.85,.65] }),\n tradeoffs: [\"Limited continuous AF; heavier digital correction and edge pupil clipping in matched reference.\"] },\n { tier: \"prosumer\", label: \"Prosumer\", presetId: \"photivra-prosumer\", presetVersion: version, scientificStatus: \"approximation\", evidence,\n body: bodyAssets(version, \"photivra-prosumer-body\", 12800, 8, 16, { bitDepth: 14, blackLevelCode: 1024, saturationElectrons: 40000,\n maximumAnalogGain: 64, lowGainReadNoise: 3, highGainReadNoise: 1.4, highGainFromIso: 800, highGainMaximumCharge: 12000,\n prnu: .006, dsnu: .2, hotFraction: 1e-4, hotMultiplier: 40, rowRms: .3, columnRms: .2, instanceSeed: 0x2c1b3c6d }, .015, .65, .01, true, true),\n lens: lensAssets(version, \"photivra-prosumer-prime\", { ...common, distortionK1: -.025, lateralCaK1Offset: .004, vignettingR2: -.25,\n breathingProjectionScale: 1.015, transmission: .85, correctionGainStrength: .6, ghostPowerFraction: .003, veilPowerFraction: .006,\n pupilAmplitudeByField: [disk, disk, clipped], pupilOpdMicrometersByDefocus: [near.map((v)=>v*.7), flat, far.map((v)=>v*.7)], pupilThroughputByField: [1,.95,.85] }),\n tradeoffs: [\"Lower matched-reference peripheral gain/noise amplification than Professional; not universally inferior.\"] },\n { tier: \"professional\", label: \"Professional\", presetId: \"photivra-professional\", presetVersion: version, scientificStatus: \"approximation\", evidence,\n body: bodyAssets(version, \"photivra-professional-body\", 25600, 12, 24, { bitDepth: 14, blackLevelCode: 1024, saturationElectrons: 60000,\n maximumAnalogGain: 128, lowGainReadNoise: 2, highGainReadNoise: 1.1, highGainFromIso: 800, highGainMaximumCharge: 16000,\n prnu: .004, dsnu: .15, hotFraction: 5e-5, hotMultiplier: 30, rowRms: .15, columnRms: .1, instanceSeed: 0x6a09e667 }, .008, .85, .02, true, true),\n lens: lensAssets(version, \"photivra-professional-prime\", { ...common, distortionK1: -.01, lateralCaK1Offset: .002, vignettingR2: -.35,\n breathingProjectionScale: 1.005, transmission: .9, correctionGainStrength: .8, ghostPowerFraction: .001, veilPowerFraction: .002,\n pupilAmplitudeByField: [disk, disk, disk], pupilOpdMicrometersByDefocus: [near.map((v)=>v*.9), flat, far.map((v)=>v*.6)], pupilThroughputByField: [1,.98,.95] }),\n tradeoffs: [\"Less edge clipping/stray light, with greater f/4 falloff/gain cost than Prosumer and asymmetric near/far wavefront character.\"] }\n ];\n}\n\n/** The presets of the current version, 2.1.0 (third-stop ISO settings). */\nexport const GENERIC_TIER_ASSETS: readonly GenericEquipmentTierPreset[] = buildGenericTierAssets(\"2.1.0\");\nlet historical: readonly GenericEquipmentTierPreset[] | undefined;\n/** The presets of an exact version; 2.0.0 (whole-stop ISO) is built on first use. */\nexport function genericTierAssets(version: GenericTierPresetVersion): readonly GenericEquipmentTierPreset[] {\n if (version === \"2.1.0\") return GENERIC_TIER_ASSETS;\n return historical ??= buildGenericTierAssets(\"2.0.0\");\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { type OpticalProfileState } from "../optics/profile-contract.js";
2
- import { type GenericEquipmentTier, type GenericEquipmentTierPreset } from "./generic-tier-assets.js";
2
+ import { type GenericEquipmentTier, type GenericEquipmentTierPreset, type GenericTierPresetVersion } from "./generic-tier-assets.js";
3
3
  import { type GenericLensCorrectionProfile } from "../output/lens-corrections.js";
4
4
  import { type LensStrayLightProfile } from "../optics/stray-light.js";
5
5
  import { type LensComplexPupilProfile } from "../optics/complex-pupil-psf.js";
@@ -7,7 +7,10 @@ import { type SceneToSensorIrradianceProfile } from "../optics/scene-to-sensor-i
7
7
  import type { RadialDistortionProfile } from "../optics/radial-distortion.js";
8
8
  import type { LateralChromaticAberrationProfile } from "../optics/lateral-chromatic-aberration.js";
9
9
  import type { IlluminationVignettingProfile } from "../optics/illumination-vignetting.js";
10
- export declare const GENERIC_EQUIPMENT_TIER_PRESET_VERSION: "2.0.0";
10
+ /** The current preset version (2.14: 2.1.0, third-stop ISO settings). */
11
+ export declare const GENERIC_EQUIPMENT_TIER_PRESET_VERSION: "2.1.0";
12
+ /** Every exact preset version that resolves, oldest first. A version is never retuned in place (`test/generic-tier-presets.test.ts`). */
13
+ export declare const GENERIC_EQUIPMENT_TIER_PRESET_VERSIONS: readonly ["2.0.0", "2.1.0"];
11
14
  export declare const GENERIC_EQUIPMENT_TIERS: readonly ["consumer", "prosumer", "professional"];
12
15
  export interface GenericEquipmentTierProfileReference {
13
16
  profileId: string;
@@ -15,7 +18,7 @@ export interface GenericEquipmentTierProfileReference {
15
18
  }
16
19
  export interface GenericEquipmentTierSelection {
17
20
  schemaVersion: "0.1.0";
18
- presetVersion: typeof GENERIC_EQUIPMENT_TIER_PRESET_VERSION;
21
+ presetVersion: GenericTierPresetVersion;
19
22
  bodyTier: GenericEquipmentTier;
20
23
  lensTier: GenericEquipmentTier;
21
24
  bodyPresetId: string;
@@ -10,24 +10,37 @@
10
10
  import { freezeOwnedData } from "../core/owned-data.js";
11
11
  import { InvalidConfigurationError } from "../core/configuration-error.js";
12
12
  import { choice, record, parseOpticalProfileState } from "../optics/profile-contract.js";
13
- import { GENERIC_TIER_ASSETS } from "./generic-tier-assets.js";
13
+ import { genericTierAssets } from "./generic-tier-assets.js";
14
14
  import { resolveGenericEquipmentExposureCapabilities } from "./exposure-capabilities.js";
15
15
  import { parseGenericLensCorrectionProfile } from "../output/lens-corrections.js";
16
16
  import { parseLensStrayLightProfile } from "../optics/stray-light.js";
17
17
  import { parseLensComplexPupilProfile } from "../optics/complex-pupil-psf.js";
18
18
  import { parseSceneToSensorIrradianceProfile } from "../optics/scene-to-sensor-irradiance.js";
19
- export const GENERIC_EQUIPMENT_TIER_PRESET_VERSION = "2.0.0";
20
- export const GENERIC_EQUIPMENT_TIERS = Object.freeze(["consumer", "prosumer", "professional"]);
21
- const catalog = freezeOwnedData(GENERIC_TIER_ASSETS);
22
- function preset(tier) {
23
- return catalog.find((p) => p.tier === tier);
19
+ /** The current preset version (2.14: 2.1.0, third-stop ISO settings). */
20
+ export const GENERIC_EQUIPMENT_TIER_PRESET_VERSION = "2.1.0";
21
+ /** Every exact preset version that resolves, oldest first. A version is never retuned in place (`test/generic-tier-presets.test.ts`). */
22
+ export const GENERIC_EQUIPMENT_TIER_PRESET_VERSIONS = /* @__PURE__ */ Object.freeze(["2.0.0", "2.1.0"]);
23
+ export const GENERIC_EQUIPMENT_TIERS = /* @__PURE__ */ Object.freeze(["consumer", "prosumer", "professional"]);
24
+ const catalogs = new Map();
25
+ function catalogOf(version) {
26
+ let catalog = catalogs.get(version);
27
+ if (!catalog)
28
+ catalogs.set(version, catalog = freezeOwnedData(genericTierAssets(version)));
29
+ return catalog;
30
+ }
31
+ function preset(version, tier) {
32
+ return catalogOf(version).find((p) => p.tier === tier);
33
+ }
34
+ function exactVersion(value) {
35
+ if (!GENERIC_EQUIPMENT_TIER_PRESET_VERSIONS.includes(value)) {
36
+ throw new InvalidConfigurationError("Unknown equipment preset version; historical definitions may not silently fall back.");
37
+ }
38
+ return value;
24
39
  }
25
40
  /** Catalog of exact versions. No hidden "latest" alias and no default sensor size. */
26
41
  export function resolveGenericEquipmentTierCatalog(input) {
27
42
  const r = record(input, ["presetVersion"]);
28
- if (r.presetVersion !== GENERIC_EQUIPMENT_TIER_PRESET_VERSION)
29
- throw new InvalidConfigurationError("Unknown equipment preset version; historical definitions may not silently fall back.");
30
- return catalog;
43
+ return catalogOf(exactVersion(r.presetVersion));
31
44
  }
32
45
  function bodyReferences(p) {
33
46
  const b = p.body;
@@ -39,10 +52,10 @@ function bodyReferences(p) {
39
52
  /** The lens tier matches the body tier by default. Mixing tiers is a normal, supported choice. */
40
53
  export function createGenericEquipmentTierSelection(input) {
41
54
  const r = record(input, ["presetVersion", "bodyTier", "lensTier"]);
42
- resolveGenericEquipmentTierCatalog({ presetVersion: r.presetVersion });
55
+ const presetVersion = exactVersion(r.presetVersion);
43
56
  const bodyTier = choice(r.bodyTier, GENERIC_EQUIPMENT_TIERS), lensTier = choice(r.lensTier === undefined ? bodyTier : r.lensTier, GENERIC_EQUIPMENT_TIERS);
44
- const body = preset(bodyTier), lens = preset(lensTier);
45
- return freezeOwnedData({ schemaVersion: "0.1.0", presetVersion: GENERIC_EQUIPMENT_TIER_PRESET_VERSION, bodyTier, lensTier,
57
+ const body = preset(presetVersion, bodyTier), lens = preset(presetVersion, lensTier);
58
+ return freezeOwnedData({ schemaVersion: "0.1.0", presetVersion, bodyTier, lensTier,
46
59
  bodyPresetId: body.presetId + ":body", lensPresetId: lens.presetId + ":lens",
47
60
  profileReferences: [...bodyReferences(body), { profileId: lens.lens.exposure.profileId, profileVersion: lens.lens.exposure.profileVersion }, ...lens.lens.profileReferences],
48
61
  sensorFormatSelectedByTier: false, scientificTierMultiplierApplied: false });
@@ -67,7 +80,7 @@ export function parseGenericEquipmentTierSelection(value) {
67
80
  /** Ties the finite matched-reference optical data to one exact generic selected state. Never extrapolates. */
68
81
  export function resolveGenericEquipmentTierLensProfiles(input) {
69
82
  const request = record(input, ["selection", "state"]), selection = parseGenericEquipmentTierSelection(request.selection), state = parseOpticalProfileState(request.state);
70
- const b = preset(selection.bodyTier), l = preset(selection.lensTier), a = l.lens.matchedReference;
83
+ const b = preset(selection.presetVersion, selection.bodyTier), l = preset(selection.presetVersion, selection.lensTier), a = l.lens.matchedReference;
71
84
  if (state.bodyId !== b.body.exposure.profileId.replace(/:exposure$/, "") || state.bodyVersion !== selection.presetVersion ||
72
85
  state.lensId !== l.lens.exposure.profileId.replace(/:exposure$/, "") || state.lensVersion !== selection.presetVersion ||
73
86
  state.focalLengthMm !== a.focalLengthMm || state.aperture !== a.aperture || state.focusDistanceM !== a.focusDistanceM ||