@photivra/engine 2.0.0 → 2.2.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 (77) hide show
  1. package/CHANGELOG.md +39 -1
  2. package/CITATION.cff +1 -1
  3. package/README.md +6 -6
  4. package/SECURITY.md +1 -1
  5. package/dist/capture/export-jpeg.js +7 -1
  6. package/dist/capture/export-jpeg.js.map +1 -1
  7. package/dist/capture/native-environment-lean.js +5 -2
  8. package/dist/capture/native-environment-lean.js.map +1 -1
  9. package/dist/capture/native-environment-raw.js +2 -2
  10. package/dist/capture/native-environment-raw.js.map +1 -1
  11. package/dist/capture/native-raw-development.js +1 -1
  12. package/dist/capture/native-raw-development.js.map +1 -1
  13. package/dist/capture/native-raw.d.ts +16 -0
  14. package/dist/capture/native-raw.js +16 -3
  15. package/dist/capture/native-raw.js.map +1 -1
  16. package/dist/capture/packed-sensor-raw.d.ts +7 -0
  17. package/dist/capture/packed-sensor-raw.js +6 -2
  18. package/dist/capture/packed-sensor-raw.js.map +1 -1
  19. package/dist/core/pixel-limits.d.ts +14 -0
  20. package/dist/core/pixel-limits.js +40 -0
  21. package/dist/core/pixel-limits.js.map +1 -0
  22. package/dist/core/version.d.ts +1 -1
  23. package/dist/core/version.js +1 -1
  24. package/dist/core/version.js.map +1 -1
  25. package/dist/facade/chart-radiance-batch.d.ts +7 -0
  26. package/dist/facade/chart-radiance-batch.js +7 -3
  27. package/dist/facade/chart-radiance-batch.js.map +1 -1
  28. package/dist/facade/diffraction-provider.d.ts +30 -0
  29. package/dist/facade/diffraction-provider.js +127 -0
  30. package/dist/facade/diffraction-provider.js.map +1 -0
  31. package/dist/facade/host-yield.d.ts +1 -1
  32. package/dist/facade/host-yield.js +0 -4
  33. package/dist/facade/host-yield.js.map +1 -1
  34. package/dist/facade/simulate-capture.d.ts +88 -2
  35. package/dist/facade/simulate-capture.js +343 -41
  36. package/dist/facade/simulate-capture.js.map +1 -1
  37. package/dist/index.d.ts +5 -2
  38. package/dist/index.js +4 -2
  39. package/dist/index.js.map +1 -1
  40. package/dist/motion/temporal-exposure-sum.d.ts +7 -0
  41. package/dist/motion/temporal-exposure-sum.js +6 -2
  42. package/dist/motion/temporal-exposure-sum.js.map +1 -1
  43. package/dist/optics/diffraction-psf-profile.d.ts +118 -0
  44. package/dist/optics/diffraction-psf-profile.js +252 -0
  45. package/dist/optics/diffraction-psf-profile.js.map +1 -0
  46. package/dist/optics/irradiance-convolution.d.ts +7 -0
  47. package/dist/optics/irradiance-convolution.js +6 -2
  48. package/dist/optics/irradiance-convolution.js.map +1 -1
  49. package/dist/output/native-capture-sdr.d.ts +7 -0
  50. package/dist/output/native-capture-sdr.js +6 -3
  51. package/dist/output/native-capture-sdr.js.map +1 -1
  52. package/dist/output/png-encoder.d.ts +10 -1
  53. package/dist/output/png-encoder.js +10 -4
  54. package/dist/output/png-encoder.js.map +1 -1
  55. package/dist/output/print-jpeg.d.ts +18 -0
  56. package/dist/output/print-jpeg.js +15 -4
  57. package/dist/output/print-jpeg.js.map +1 -1
  58. package/dist/sensor/sampling-aperture.d.ts +15 -0
  59. package/dist/sensor/sampling-aperture.js +31 -10
  60. package/dist/sensor/sampling-aperture.js.map +1 -1
  61. package/docs/API_REFERENCE.md +27 -1
  62. package/docs/QUICK_START.md +285 -13
  63. package/docs/USAGE.md +3 -1
  64. package/docs/api/capture-native-raw.md +11 -2
  65. package/docs/api/capture-packed-sensor-raw.md +7 -1
  66. package/docs/api/core-pixel-limits.md +19 -0
  67. package/docs/api/core-version.md +1 -1
  68. package/docs/api/exports.json +62 -2
  69. package/docs/api/facade-chart-radiance-batch.md +8 -2
  70. package/docs/api/facade-simulate-capture.md +83 -3
  71. package/docs/api/motion-temporal-exposure-sum.md +7 -1
  72. package/docs/api/optics-diffraction-psf-profile.md +96 -0
  73. package/docs/api/optics-irradiance-convolution.md +7 -1
  74. package/docs/api/output-native-capture-sdr.md +7 -2
  75. package/docs/api/output-png-encoder.md +8 -1
  76. package/docs/api/output-print-jpeg.md +17 -0
  77. package/package.json +3 -2
@@ -1 +1 @@
1
- {"version":3,"file":"sampling-aperture.js","sourceRoot":"","sources":["../../src/sensor/sampling-aperture.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Sampling aperture: where the colour-sampling sites sit physically on the sensor, and the\n * light-sensitive area of each site as a simple geometric shape.\n *\n * Site pitch and origin are declared facts, never derived from NativeImageRaster. The sensitive\n * region, when known, is a plain geometric rectangle. It does not include microlens effects, charge\n * diffusion, electrical crosstalk, QE (quantum efficiency), throughput, spectral response or an\n * effective light-collection area.\n * @see docs/MOTION_AND_SIGNAL.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport {\n resolveNativeEffectiveRasterColorSamplingBinding,\n type NativeEffectiveRasterColorSamplingBindingProfile\n} from \"./capture-color-sampling-binding.js\";\nimport {\n resolveColorSamplingSite,\n type NativeColorSamplingSiteIndex,\n type SensorColorSamplingProfile\n} from \"./color-sampling.js\";\nimport type {\n NativeImageRaster,\n SensorImagingArea\n} from \"./sensor-geometry.js\";\nimport { requireInputObject, requireInputKeys, rejectUnknownFields } from \"../core/record-validation.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport interface SensorSiteCenterLatticeRegistration {\n kind: \"regular-rectangular-site-center-lattice\";\n coordinateSystem: \"native-sensor-physical\";\n /** Horizontal centre-to-centre site spacing (pitch) in micrometres. */\n pitchXMicrometers: number;\n /** Vertical centre-to-centre site spacing (pitch) in micrometres. */\n pitchYMicrometers: number;\n /**\n * Centre of the first site, measured from the imaging area's physical\n * top-left corner. +X right, +Y down. Units: micrometres.\n */\n firstSiteCenterFromImagingAreaTopLeftMicrometers: {\n x: number;\n y: number;\n };\n evidence: readonly EvidenceProvenance[];\n}\n\nexport type SensorGeometricSensitiveAperture =\n | {\n /**\n * The light-sensitive area is known to matter, but its shape is not\n * known well enough to use.\n */\n kind: \"unresolved\";\n evidence: readonly EvidenceProvenance[];\n }\n | {\n /**\n * A simple approximation of the sensitive area as a rectangle.\n *\n * The rectangle must stay inside one grid cell, so neighbouring\n * sensitive areas never overlap in schema 0.1.0.\n */\n kind: \"uniform-axis-aligned-rectangle\";\n widthMicrometers: number;\n heightMicrometers: number;\n centerOffsetFromSiteCenterMicrometers: {\n x: number;\n y: number;\n };\n evidence: readonly EvidenceProvenance[];\n };\n\nexport interface SensorSamplingApertureProfile {\n schemaVersion: \"0.1.0\";\n profileId: string;\n colorSamplingProfileId: string;\n colorSamplingBindingId: string;\n evidence: readonly EvidenceProvenance[];\n siteCenterLattice: SensorSiteCenterLatticeRegistration;\n geometricSensitiveAperture: SensorGeometricSensitiveAperture;\n}\n\nexport interface ResolveSensorSamplingApertureInput {\n imagingArea: SensorImagingArea;\n nativeRaster: NativeImageRaster;\n colorSamplingProfile: SensorColorSamplingProfile;\n colorSamplingBindingProfile: NativeEffectiveRasterColorSamplingBindingProfile;\n samplingApertureProfile: SensorSamplingApertureProfile;\n site: NativeColorSamplingSiteIndex;\n}\n\nexport interface NativeSensorPhysicalPointMm {\n x: number;\n y: number;\n}\n\nexport interface NativeSensorPhysicalBoundsMm {\n left: number;\n right: number;\n top: number;\n bottom: number;\n}\n\nexport interface ResolvedSensorSamplingAperture {\n profileId: string;\n colorSamplingProfileId: string;\n colorSamplingBindingId: string;\n coordinateSystem: \"native-sensor-physical\";\n site: NativeColorSamplingSiteIndex;\n channelId: string;\n siteGrid: {\n widthSites: number;\n heightSites: number;\n };\n lattice: {\n pitchXMicrometers: number;\n pitchYMicrometers: number;\n firstSiteCenterFromImagingAreaTopLeftMicrometers: {\n x: number;\n y: number;\n };\n siteCenterFromImagingAreaTopLeftMicrometers: {\n x: number;\n y: number;\n };\n siteCenterFromOpticalAxisMm: NativeSensorPhysicalPointMm;\n nominalCellAreaSquareMicrometers: number;\n };\n geometricSensitiveAperture: {\n kind: \"uniform-axis-aligned-rectangle\";\n widthMicrometers: number;\n heightMicrometers: number;\n centerOffsetFromSiteCenterMicrometers: {\n x: number;\n y: number;\n };\n centerFromOpticalAxisMm: NativeSensorPhysicalPointMm;\n boundsFromOpticalAxisMm: NativeSensorPhysicalBoundsMm;\n areaSquareMicrometers: number;\n geometricSensitiveAreaFractionOfLatticeCell: number;\n spatialWeighting:\n \"uniform-unit-area-average\";\n neighboringGeometricApertureOverlap:\n \"none-by-model\";\n };\n /**\n * Fixed statements of what this result does not establish.\n */\n sitePitchDerivedFromNativeImageRaster: false;\n apertureDerivedFromSitePitch: false;\n antiAliasingResponseIncluded: false;\n microlensSpatialRedistributionIncluded: false;\n chargeDiffusionIncluded: false;\n electricalCrosstalkIncluded: false;\n spectralResponseIncluded: false;\n quantumEfficiencyIncluded: false;\n opticalThroughputIncluded: false;\n radiometricCollectionAreaEstablished: false;\n physicalPhotodiodeGeometryEstablished: false;\n provenance: {\n profile: readonly EvidenceProvenance[];\n lattice: readonly EvidenceProvenance[];\n aperture: readonly EvidenceProvenance[];\n };\n}\n\nfunction requireRecord(\n value: unknown,\n path: string,\n allowedKeys: readonly string[] | null\n): UnknownRecord {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be an object.\"\n );\n }\n if (allowedKeys !== null) rejectUnknownFields(value, allowedKeys, path);\n return value as UnknownRecord;\n}\n\nfunction requireNonEmptyString(\n value: unknown,\n path: string\n): string {\n if (\n typeof value !== \"string\" ||\n value.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n path + \" must be a non-empty string.\"\n );\n }\n return value;\n}\n\nfunction requirePositiveFinite(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n value <= 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must be a finite number greater than zero.\"\n );\n }\n return value;\n}\n\nfunction requireFinite(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be a finite number.\"\n );\n }\n return value;\n}\n\nfunction parseSiteCenterLattice(\n value: unknown,\n path: string\n): SensorSiteCenterLatticeRegistration {\n const record = requireRecord(value, path, [\"kind\", \"coordinateSystem\", \"firstSiteCenterFromImagingAreaTopLeftMicrometers\", \"pitchXMicrometers\", \"pitchYMicrometers\", \"evidence\"]);\n\n if (\n record.kind !==\n \"regular-rectangular-site-center-lattice\"\n ) {\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n }\n if (\n record.coordinateSystem !==\n \"native-sensor-physical\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.coordinateSystem must be \"native-sensor-physical\".'\n );\n }\n\n const firstCenter = requireRecord(\n record.firstSiteCenterFromImagingAreaTopLeftMicrometers,\n path +\n \".firstSiteCenterFromImagingAreaTopLeftMicrometers\", [\"x\", \"y\"]\n );\n\n const firstX = requireFinite(\n firstCenter.x,\n path +\n \".firstSiteCenterFromImagingAreaTopLeftMicrometers.x\"\n );\n const firstY = requireFinite(\n firstCenter.y,\n path +\n \".firstSiteCenterFromImagingAreaTopLeftMicrometers.y\"\n );\n\n if (firstX < 0 || firstY < 0) {\n throw new InvalidConfigurationError(\n path +\n \".firstSiteCenterFromImagingAreaTopLeftMicrometers must not be negative.\"\n );\n }\n\n return {\n kind:\n \"regular-rectangular-site-center-lattice\",\n coordinateSystem:\n \"native-sensor-physical\",\n pitchXMicrometers:\n requirePositiveFinite(\n record.pitchXMicrometers,\n path + \".pitchXMicrometers\"\n ),\n pitchYMicrometers:\n requirePositiveFinite(\n record.pitchYMicrometers,\n path + \".pitchYMicrometers\"\n ),\n firstSiteCenterFromImagingAreaTopLeftMicrometers:\n {\n x: firstX,\n y: firstY\n },\n evidence: parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\nfunction parseGeometricSensitiveAperture(\n value: unknown,\n path: string,\n lattice: SensorSiteCenterLatticeRegistration\n): SensorGeometricSensitiveAperture {\n const record = requireRecord(value, path, [\"kind\", \"widthMicrometers\", \"heightMicrometers\", \"centerOffsetFromSiteCenterMicrometers\", \"evidence\"]);\n\n if (record.kind === \"unresolved\") {\n if (\n record.widthMicrometers !== undefined ||\n record.heightMicrometers !== undefined ||\n record.centerOffsetFromSiteCenterMicrometers !==\n undefined\n ) {\n throw new InvalidConfigurationError(\n path +\n \" unresolved aperture must omit rectangle fields.\"\n );\n }\n return {\n kind: \"unresolved\",\n evidence: parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n }\n\n if (\n record.kind !==\n \"uniform-axis-aligned-rectangle\"\n ) {\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n }\n\n const widthMicrometers =\n requirePositiveFinite(\n record.widthMicrometers,\n path + \".widthMicrometers\"\n );\n const heightMicrometers =\n requirePositiveFinite(\n record.heightMicrometers,\n path + \".heightMicrometers\"\n );\n const offset = requireRecord(\n record.centerOffsetFromSiteCenterMicrometers,\n path +\n \".centerOffsetFromSiteCenterMicrometers\", [\"x\", \"y\"]\n );\n const offsetX = requireFinite(\n offset.x,\n path +\n \".centerOffsetFromSiteCenterMicrometers.x\"\n );\n const offsetY = requireFinite(\n offset.y,\n path +\n \".centerOffsetFromSiteCenterMicrometers.y\"\n );\n\n const halfCellX =\n lattice.pitchXMicrometers / 2;\n const halfCellY =\n lattice.pitchYMicrometers / 2;\n\n if (\n Math.abs(offsetX) +\n widthMicrometers / 2 >\n halfCellX ||\n Math.abs(offsetY) +\n heightMicrometers / 2 >\n halfCellY\n ) {\n throw new InvalidConfigurationError(\n path +\n \" rectangle must remain within one regular site lattice cell.\"\n );\n }\n\n return {\n kind:\n \"uniform-axis-aligned-rectangle\",\n widthMicrometers,\n heightMicrometers,\n centerOffsetFromSiteCenterMicrometers:\n {\n x: offsetX,\n y: offsetY\n },\n evidence: parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\n/**\n * Parses where the colour-sampling sites sit physically, plus a simple geometric\n * model of each site's light-sensitive area.\n *\n * Site pitch and origin are declared facts, never derived from NativeImageRaster.\n * The rectangle, when given, is a geometric sensitive region only. It does not\n * include microlens effects, charge diffusion, electrical crosstalk, QE,\n * throughput, spectral response or an effective light-collection area.\n */\nexport function parseSensorSamplingApertureProfile(\n value: unknown\n): SensorSamplingApertureProfile {\n const profile = requireRecord(\n value,\n \"sensorSamplingAperture\", [\"schemaVersion\", \"siteCenterLattice\", \"profileId\", \"colorSamplingProfileId\", \"colorSamplingBindingId\", \"evidence\", \"geometricSensitiveAperture\"]\n );\n\n if (profile.schemaVersion !== \"0.1.0\") {\n throw new InvalidConfigurationError(\n 'sensorSamplingAperture.schemaVersion must be \"0.1.0\".'\n );\n }\n\n const siteCenterLattice =\n parseSiteCenterLattice(\n profile.siteCenterLattice,\n \"sensorSamplingAperture.siteCenterLattice\"\n );\n\n return {\n schemaVersion: \"0.1.0\",\n profileId: requireNonEmptyString(\n profile.profileId,\n \"sensorSamplingAperture.profileId\"\n ),\n colorSamplingProfileId:\n requireNonEmptyString(\n profile.colorSamplingProfileId,\n \"sensorSamplingAperture.colorSamplingProfileId\"\n ),\n colorSamplingBindingId:\n requireNonEmptyString(\n profile.colorSamplingBindingId,\n \"sensorSamplingAperture.colorSamplingBindingId\"\n ),\n evidence: parseEvidenceList(\n profile.evidence,\n \"sensorSamplingAperture.evidence\"\n ),\n siteCenterLattice,\n geometricSensitiveAperture:\n parseGeometricSensitiveAperture(\n profile.geometricSensitiveAperture,\n \"sensorSamplingAperture.geometricSensitiveAperture\",\n siteCenterLattice\n )\n };\n}\n\nfunction requireSiteIndex(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isSafeInteger(value) ||\n value < 0\n ) {\n throw new InvalidScientificInputError(\n path +\n \" must be a non-negative safe integer color-sampling-site index.\"\n );\n }\n return value;\n}\n\nfunction requirePositiveImagingArea(\n imagingArea: SensorImagingArea\n): void {\n requireInputObject(imagingArea, \"imagingArea input\");\n if (\n !Number.isFinite(imagingArea.widthMm) ||\n imagingArea.widthMm <= 0 ||\n !Number.isFinite(imagingArea.heightMm) ||\n imagingArea.heightMm <= 0\n ) {\n throw new InvalidScientificInputError(\n \"imagingArea width/height must be finite and greater than zero.\"\n );\n }\n}\n\n/**\n * Resolves one site's geometric sampling aperture in native sensor physical space.\n *\n * The result is a normalized footprint that averages evenly over its area, for\n * image sampling, plus its physical area and fill fraction. That geometric area\n * is deliberately not treated as light-collection efficiency or as the true\n * photodiode shape.\n */\nexport function resolveSensorSamplingAperture(\n input: ResolveSensorSamplingApertureInput\n): ResolvedSensorSamplingAperture {\n requireInputKeys(input, \"resolveSensorSamplingAperture\", [\"imagingArea\", \"nativeRaster\", \"colorSamplingProfile\", \"colorSamplingBindingProfile\", \"samplingApertureProfile\", \"site\"]);\n requirePositiveImagingArea(\n input.imagingArea\n );\n\n const profile =\n parseSensorSamplingApertureProfile(\n input.samplingApertureProfile\n );\n const binding =\n resolveNativeEffectiveRasterColorSamplingBinding(\n {\n nativeRaster: input.nativeRaster,\n colorSamplingProfile:\n input.colorSamplingProfile,\n bindingProfile:\n input.colorSamplingBindingProfile\n }\n );\n\n if (\n profile.colorSamplingProfileId !==\n binding.colorSamplingProfileId\n ) {\n throw new InvalidScientificInputError(\n \"Sampling-aperture colorSamplingProfileId must match the resolved color-sampling profile.\"\n );\n }\n if (\n profile.colorSamplingBindingId !==\n binding.bindingId\n ) {\n throw new InvalidScientificInputError(\n \"Sampling-aperture colorSamplingBindingId must match the resolved color-sampling binding.\"\n );\n }\n\n if (\n profile.geometricSensitiveAperture.kind ===\n \"unresolved\"\n ) {\n throw new InvalidScientificInputError(\n \"Geometric sensitive aperture is unresolved; a spatial sampling aperture cannot be produced.\"\n );\n }\n\n const siteX = requireSiteIndex(\n input.site.x,\n \"site.x\"\n );\n const siteY = requireSiteIndex(\n input.site.y,\n \"site.y\"\n );\n\n if (\n siteX >=\n binding.colorSamplingSiteGrid.widthSites ||\n siteY >=\n binding.colorSamplingSiteGrid.heightSites\n ) {\n throw new InvalidScientificInputError(\n \"site must lie within the bound color-sampling site grid.\"\n );\n }\n\n const lattice =\n profile.siteCenterLattice;\n const gridWidth =\n binding.colorSamplingSiteGrid.widthSites;\n const gridHeight =\n binding.colorSamplingSiteGrid.heightSites;\n const imagingWidthMicrometers =\n input.imagingArea.widthMm * 1000;\n const imagingHeightMicrometers =\n input.imagingArea.heightMm * 1000;\n\n const lastCenterX =\n lattice\n .firstSiteCenterFromImagingAreaTopLeftMicrometers\n .x +\n (gridWidth - 1) *\n lattice.pitchXMicrometers;\n const lastCenterY =\n lattice\n .firstSiteCenterFromImagingAreaTopLeftMicrometers\n .y +\n (gridHeight - 1) *\n lattice.pitchYMicrometers;\n\n if (\n lastCenterX > imagingWidthMicrometers ||\n lastCenterY > imagingHeightMicrometers\n ) {\n throw new InvalidScientificInputError(\n \"Declared site-center lattice extends beyond the supplied physical imaging area.\"\n );\n }\n\n const aperture =\n profile.geometricSensitiveAperture;\n const apertureOffsetX =\n aperture.centerOffsetFromSiteCenterMicrometers.x;\n const apertureOffsetY =\n aperture.centerOffsetFromSiteCenterMicrometers.y;\n const apertureHalfWidth =\n aperture.widthMicrometers / 2;\n const apertureHalfHeight =\n aperture.heightMicrometers / 2;\n\n const firstApertureLeft =\n lattice.firstSiteCenterFromImagingAreaTopLeftMicrometers.x +\n apertureOffsetX -\n apertureHalfWidth;\n const firstApertureTop =\n lattice.firstSiteCenterFromImagingAreaTopLeftMicrometers.y +\n apertureOffsetY -\n apertureHalfHeight;\n const lastApertureRight =\n lastCenterX +\n apertureOffsetX +\n apertureHalfWidth;\n const lastApertureBottom =\n lastCenterY +\n apertureOffsetY +\n apertureHalfHeight;\n\n if (\n firstApertureLeft < 0 ||\n firstApertureTop < 0 ||\n lastApertureRight > imagingWidthMicrometers ||\n lastApertureBottom > imagingHeightMicrometers\n ) {\n throw new InvalidScientificInputError(\n \"Declared geometric sensitive aperture does not fit within the supplied physical imaging area across the complete site grid.\"\n );\n }\n\n const siteCenterFromTopLeftX =\n lattice\n .firstSiteCenterFromImagingAreaTopLeftMicrometers\n .x +\n siteX * lattice.pitchXMicrometers;\n const siteCenterFromTopLeftY =\n lattice\n .firstSiteCenterFromImagingAreaTopLeftMicrometers\n .y +\n siteY * lattice.pitchYMicrometers;\n\n const apertureCenterFromTopLeftX =\n siteCenterFromTopLeftX +\n aperture\n .centerOffsetFromSiteCenterMicrometers\n .x;\n const apertureCenterFromTopLeftY =\n siteCenterFromTopLeftY +\n aperture\n .centerOffsetFromSiteCenterMicrometers\n .y;\n const apertureLeftTopX =\n apertureCenterFromTopLeftX -\n aperture.widthMicrometers / 2;\n const apertureRightBottomX =\n apertureCenterFromTopLeftX +\n aperture.widthMicrometers / 2;\n const apertureLeftTopY =\n apertureCenterFromTopLeftY -\n aperture.heightMicrometers / 2;\n const apertureRightBottomY =\n apertureCenterFromTopLeftY +\n aperture.heightMicrometers / 2;\n\n if (\n apertureLeftTopX < 0 ||\n apertureLeftTopY < 0 ||\n apertureRightBottomX >\n imagingWidthMicrometers ||\n apertureRightBottomY >\n imagingHeightMicrometers\n ) {\n throw new InvalidScientificInputError(\n \"Resolved geometric sensitive aperture extends beyond the supplied physical imaging area.\"\n );\n }\n\n const siteCenterFromOpticalAxisMm = {\n x:\n -input.imagingArea.widthMm / 2 +\n siteCenterFromTopLeftX / 1000,\n y:\n -input.imagingArea.heightMm / 2 +\n siteCenterFromTopLeftY / 1000\n };\n const apertureCenterFromOpticalAxisMm = {\n x:\n -input.imagingArea.widthMm / 2 +\n apertureCenterFromTopLeftX / 1000,\n y:\n -input.imagingArea.heightMm / 2 +\n apertureCenterFromTopLeftY / 1000\n };\n const boundsFromOpticalAxisMm = {\n left:\n -input.imagingArea.widthMm / 2 +\n apertureLeftTopX / 1000,\n right:\n -input.imagingArea.widthMm / 2 +\n apertureRightBottomX / 1000,\n top:\n -input.imagingArea.heightMm / 2 +\n apertureLeftTopY / 1000,\n bottom:\n -input.imagingArea.heightMm / 2 +\n apertureRightBottomY / 1000\n };\n\n const areaSquareMicrometers =\n aperture.widthMicrometers *\n aperture.heightMicrometers;\n const nominalCellAreaSquareMicrometers =\n lattice.pitchXMicrometers *\n lattice.pitchYMicrometers;\n const geometricSensitiveAreaFractionOfLatticeCell =\n areaSquareMicrometers /\n nominalCellAreaSquareMicrometers;\n\n if (\n !Number.isFinite(areaSquareMicrometers) ||\n !Number.isFinite(\n nominalCellAreaSquareMicrometers\n ) ||\n !Number.isFinite(\n geometricSensitiveAreaFractionOfLatticeCell\n )\n ) {\n throw new InvalidScientificInputError(\n \"Derived sampling-aperture geometry must remain finite.\"\n );\n }\n\n const channel =\n resolveColorSamplingSite({\n profile: input.colorSamplingProfile,\n site: {\n x: siteX,\n y: siteY\n }\n });\n\n return {\n profileId: profile.profileId,\n colorSamplingProfileId:\n profile.colorSamplingProfileId,\n colorSamplingBindingId:\n profile.colorSamplingBindingId,\n coordinateSystem:\n \"native-sensor-physical\",\n site: {\n x: siteX,\n y: siteY\n },\n channelId: channel.mapping.channelId,\n siteGrid: {\n widthSites: gridWidth,\n heightSites: gridHeight\n },\n lattice: {\n pitchXMicrometers:\n lattice.pitchXMicrometers,\n pitchYMicrometers:\n lattice.pitchYMicrometers,\n firstSiteCenterFromImagingAreaTopLeftMicrometers:\n {\n ...lattice\n .firstSiteCenterFromImagingAreaTopLeftMicrometers\n },\n siteCenterFromImagingAreaTopLeftMicrometers:\n {\n x: siteCenterFromTopLeftX,\n y: siteCenterFromTopLeftY\n },\n siteCenterFromOpticalAxisMm,\n nominalCellAreaSquareMicrometers\n },\n geometricSensitiveAperture: {\n kind:\n \"uniform-axis-aligned-rectangle\",\n widthMicrometers:\n aperture.widthMicrometers,\n heightMicrometers:\n aperture.heightMicrometers,\n centerOffsetFromSiteCenterMicrometers:\n {\n ...aperture\n .centerOffsetFromSiteCenterMicrometers\n },\n centerFromOpticalAxisMm:\n apertureCenterFromOpticalAxisMm,\n boundsFromOpticalAxisMm,\n areaSquareMicrometers,\n geometricSensitiveAreaFractionOfLatticeCell,\n spatialWeighting:\n \"uniform-unit-area-average\",\n neighboringGeometricApertureOverlap:\n \"none-by-model\"\n },\n sitePitchDerivedFromNativeImageRaster:\n false,\n apertureDerivedFromSitePitch: false,\n antiAliasingResponseIncluded: false,\n microlensSpatialRedistributionIncluded:\n false,\n chargeDiffusionIncluded: false,\n electricalCrosstalkIncluded: false,\n spectralResponseIncluded: false,\n quantumEfficiencyIncluded: false,\n opticalThroughputIncluded: false,\n radiometricCollectionAreaEstablished:\n false,\n physicalPhotodiodeGeometryEstablished:\n false,\n provenance: {\n profile: profile.evidence,\n lattice: lattice.evidence,\n aperture: aperture.evidence\n }\n };\n}\n"]}
1
+ {"version":3,"file":"sampling-aperture.js","sourceRoot":"","sources":["../../src/sensor/sampling-aperture.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Sampling aperture: where the colour-sampling sites sit physically on the sensor, and the\n * light-sensitive area of each site as a simple geometric shape.\n *\n * Site pitch and origin are declared facts, never derived from NativeImageRaster. The sensitive\n * region, when known, is a plain geometric rectangle. It does not include microlens effects, charge\n * diffusion, electrical crosstalk, QE (quantum efficiency), throughput, spectral response or an\n * effective light-collection area.\n * @see docs/MOTION_AND_SIGNAL.md for equations, coordinate/unit conventions, blockers and support\n * limits.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\nimport {\n resolveNativeEffectiveRasterColorSamplingBinding,\n type NativeEffectiveRasterColorSamplingBindingProfile\n} from \"./capture-color-sampling-binding.js\";\nimport {\n resolveColorSamplingSite,\n type NativeColorSamplingSiteIndex,\n type SensorColorSamplingProfile\n} from \"./color-sampling.js\";\nimport type {\n NativeImageRaster,\n SensorImagingArea\n} from \"./sensor-geometry.js\";\nimport { requireInputObject, requireInputKeys, rejectUnknownFields } from \"../core/record-validation.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport interface SensorSiteCenterLatticeRegistration {\n kind: \"regular-rectangular-site-center-lattice\";\n coordinateSystem: \"native-sensor-physical\";\n /** Horizontal centre-to-centre site spacing (pitch) in micrometres. */\n pitchXMicrometers: number;\n /** Vertical centre-to-centre site spacing (pitch) in micrometres. */\n pitchYMicrometers: number;\n /**\n * Centre of the first site, measured from the imaging area's physical\n * top-left corner. +X right, +Y down. Units: micrometres.\n */\n firstSiteCenterFromImagingAreaTopLeftMicrometers: {\n x: number;\n y: number;\n };\n evidence: readonly EvidenceProvenance[];\n}\n\nexport type SensorGeometricSensitiveAperture =\n | {\n /**\n * The light-sensitive area is known to matter, but its shape is not\n * known well enough to use.\n */\n kind: \"unresolved\";\n evidence: readonly EvidenceProvenance[];\n }\n | {\n /**\n * A simple approximation of the sensitive area as a rectangle.\n *\n * The rectangle must stay inside one grid cell, so neighbouring\n * sensitive areas never overlap in schema 0.1.0.\n */\n kind: \"uniform-axis-aligned-rectangle\";\n widthMicrometers: number;\n heightMicrometers: number;\n centerOffsetFromSiteCenterMicrometers: {\n x: number;\n y: number;\n };\n evidence: readonly EvidenceProvenance[];\n };\n\nexport interface SensorSamplingApertureProfile {\n schemaVersion: \"0.1.0\";\n profileId: string;\n colorSamplingProfileId: string;\n colorSamplingBindingId: string;\n evidence: readonly EvidenceProvenance[];\n siteCenterLattice: SensorSiteCenterLatticeRegistration;\n geometricSensitiveAperture: SensorGeometricSensitiveAperture;\n}\n\nexport interface ResolveSensorSamplingApertureInput {\n imagingArea: SensorImagingArea;\n nativeRaster: NativeImageRaster;\n colorSamplingProfile: SensorColorSamplingProfile;\n colorSamplingBindingProfile: NativeEffectiveRasterColorSamplingBindingProfile;\n samplingApertureProfile: SensorSamplingApertureProfile;\n site: NativeColorSamplingSiteIndex;\n}\n\nexport interface NativeSensorPhysicalPointMm {\n x: number;\n y: number;\n}\n\nexport interface NativeSensorPhysicalBoundsMm {\n left: number;\n right: number;\n top: number;\n bottom: number;\n}\n\nexport interface ResolvedSensorSamplingAperture {\n profileId: string;\n colorSamplingProfileId: string;\n colorSamplingBindingId: string;\n coordinateSystem: \"native-sensor-physical\";\n site: NativeColorSamplingSiteIndex;\n channelId: string;\n siteGrid: {\n widthSites: number;\n heightSites: number;\n };\n lattice: {\n pitchXMicrometers: number;\n pitchYMicrometers: number;\n firstSiteCenterFromImagingAreaTopLeftMicrometers: {\n x: number;\n y: number;\n };\n siteCenterFromImagingAreaTopLeftMicrometers: {\n x: number;\n y: number;\n };\n siteCenterFromOpticalAxisMm: NativeSensorPhysicalPointMm;\n nominalCellAreaSquareMicrometers: number;\n };\n geometricSensitiveAperture: {\n kind: \"uniform-axis-aligned-rectangle\";\n widthMicrometers: number;\n heightMicrometers: number;\n centerOffsetFromSiteCenterMicrometers: {\n x: number;\n y: number;\n };\n centerFromOpticalAxisMm: NativeSensorPhysicalPointMm;\n boundsFromOpticalAxisMm: NativeSensorPhysicalBoundsMm;\n areaSquareMicrometers: number;\n geometricSensitiveAreaFractionOfLatticeCell: number;\n spatialWeighting:\n \"uniform-unit-area-average\";\n neighboringGeometricApertureOverlap:\n \"none-by-model\";\n };\n /**\n * Fixed statements of what this result does not establish.\n */\n sitePitchDerivedFromNativeImageRaster: false;\n apertureDerivedFromSitePitch: false;\n antiAliasingResponseIncluded: false;\n microlensSpatialRedistributionIncluded: false;\n chargeDiffusionIncluded: false;\n electricalCrosstalkIncluded: false;\n spectralResponseIncluded: false;\n quantumEfficiencyIncluded: false;\n opticalThroughputIncluded: false;\n radiometricCollectionAreaEstablished: false;\n physicalPhotodiodeGeometryEstablished: false;\n provenance: {\n profile: readonly EvidenceProvenance[];\n lattice: readonly EvidenceProvenance[];\n aperture: readonly EvidenceProvenance[];\n };\n}\n\nfunction requireRecord(\n value: unknown,\n path: string,\n allowedKeys: readonly string[] | null\n): UnknownRecord {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be an object.\"\n );\n }\n if (allowedKeys !== null) rejectUnknownFields(value, allowedKeys, path);\n return value as UnknownRecord;\n}\n\nfunction requireNonEmptyString(\n value: unknown,\n path: string\n): string {\n if (\n typeof value !== \"string\" ||\n value.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n path + \" must be a non-empty string.\"\n );\n }\n return value;\n}\n\nfunction requirePositiveFinite(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n value <= 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must be a finite number greater than zero.\"\n );\n }\n return value;\n}\n\nfunction requireFinite(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be a finite number.\"\n );\n }\n return value;\n}\n\nfunction parseSiteCenterLattice(\n value: unknown,\n path: string\n): SensorSiteCenterLatticeRegistration {\n const record = requireRecord(value, path, [\"kind\", \"coordinateSystem\", \"firstSiteCenterFromImagingAreaTopLeftMicrometers\", \"pitchXMicrometers\", \"pitchYMicrometers\", \"evidence\"]);\n\n if (\n record.kind !==\n \"regular-rectangular-site-center-lattice\"\n ) {\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n }\n if (\n record.coordinateSystem !==\n \"native-sensor-physical\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.coordinateSystem must be \"native-sensor-physical\".'\n );\n }\n\n const firstCenter = requireRecord(\n record.firstSiteCenterFromImagingAreaTopLeftMicrometers,\n path +\n \".firstSiteCenterFromImagingAreaTopLeftMicrometers\", [\"x\", \"y\"]\n );\n\n const firstX = requireFinite(\n firstCenter.x,\n path +\n \".firstSiteCenterFromImagingAreaTopLeftMicrometers.x\"\n );\n const firstY = requireFinite(\n firstCenter.y,\n path +\n \".firstSiteCenterFromImagingAreaTopLeftMicrometers.y\"\n );\n\n if (firstX < 0 || firstY < 0) {\n throw new InvalidConfigurationError(\n path +\n \".firstSiteCenterFromImagingAreaTopLeftMicrometers must not be negative.\"\n );\n }\n\n return {\n kind:\n \"regular-rectangular-site-center-lattice\",\n coordinateSystem:\n \"native-sensor-physical\",\n pitchXMicrometers:\n requirePositiveFinite(\n record.pitchXMicrometers,\n path + \".pitchXMicrometers\"\n ),\n pitchYMicrometers:\n requirePositiveFinite(\n record.pitchYMicrometers,\n path + \".pitchYMicrometers\"\n ),\n firstSiteCenterFromImagingAreaTopLeftMicrometers:\n {\n x: firstX,\n y: firstY\n },\n evidence: parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\nfunction parseGeometricSensitiveAperture(\n value: unknown,\n path: string,\n lattice: SensorSiteCenterLatticeRegistration\n): SensorGeometricSensitiveAperture {\n const record = requireRecord(value, path, [\"kind\", \"widthMicrometers\", \"heightMicrometers\", \"centerOffsetFromSiteCenterMicrometers\", \"evidence\"]);\n\n if (record.kind === \"unresolved\") {\n if (\n record.widthMicrometers !== undefined ||\n record.heightMicrometers !== undefined ||\n record.centerOffsetFromSiteCenterMicrometers !==\n undefined\n ) {\n throw new InvalidConfigurationError(\n path +\n \" unresolved aperture must omit rectangle fields.\"\n );\n }\n return {\n kind: \"unresolved\",\n evidence: parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n }\n\n if (\n record.kind !==\n \"uniform-axis-aligned-rectangle\"\n ) {\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n }\n\n const widthMicrometers =\n requirePositiveFinite(\n record.widthMicrometers,\n path + \".widthMicrometers\"\n );\n const heightMicrometers =\n requirePositiveFinite(\n record.heightMicrometers,\n path + \".heightMicrometers\"\n );\n const offset = requireRecord(\n record.centerOffsetFromSiteCenterMicrometers,\n path +\n \".centerOffsetFromSiteCenterMicrometers\", [\"x\", \"y\"]\n );\n const offsetX = requireFinite(\n offset.x,\n path +\n \".centerOffsetFromSiteCenterMicrometers.x\"\n );\n const offsetY = requireFinite(\n offset.y,\n path +\n \".centerOffsetFromSiteCenterMicrometers.y\"\n );\n\n const halfCellX =\n lattice.pitchXMicrometers / 2;\n const halfCellY =\n lattice.pitchYMicrometers / 2;\n\n if (\n Math.abs(offsetX) +\n widthMicrometers / 2 >\n halfCellX ||\n Math.abs(offsetY) +\n heightMicrometers / 2 >\n halfCellY\n ) {\n throw new InvalidConfigurationError(\n path +\n \" rectangle must remain within one regular site lattice cell.\"\n );\n }\n\n return {\n kind:\n \"uniform-axis-aligned-rectangle\",\n widthMicrometers,\n heightMicrometers,\n centerOffsetFromSiteCenterMicrometers:\n {\n x: offsetX,\n y: offsetY\n },\n evidence: parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n )\n };\n}\n\n/**\n * Parses where the colour-sampling sites sit physically, plus a simple geometric\n * model of each site's light-sensitive area.\n *\n * Site pitch and origin are declared facts, never derived from NativeImageRaster.\n * The rectangle, when given, is a geometric sensitive region only. It does not\n * include microlens effects, charge diffusion, electrical crosstalk, QE,\n * throughput, spectral response or an effective light-collection area.\n */\nexport function parseSensorSamplingApertureProfile(\n value: unknown\n): SensorSamplingApertureProfile {\n const profile = requireRecord(\n value,\n \"sensorSamplingAperture\", [\"schemaVersion\", \"siteCenterLattice\", \"profileId\", \"colorSamplingProfileId\", \"colorSamplingBindingId\", \"evidence\", \"geometricSensitiveAperture\"]\n );\n\n if (profile.schemaVersion !== \"0.1.0\") {\n throw new InvalidConfigurationError(\n 'sensorSamplingAperture.schemaVersion must be \"0.1.0\".'\n );\n }\n\n const siteCenterLattice =\n parseSiteCenterLattice(\n profile.siteCenterLattice,\n \"sensorSamplingAperture.siteCenterLattice\"\n );\n\n return {\n schemaVersion: \"0.1.0\",\n profileId: requireNonEmptyString(\n profile.profileId,\n \"sensorSamplingAperture.profileId\"\n ),\n colorSamplingProfileId:\n requireNonEmptyString(\n profile.colorSamplingProfileId,\n \"sensorSamplingAperture.colorSamplingProfileId\"\n ),\n colorSamplingBindingId:\n requireNonEmptyString(\n profile.colorSamplingBindingId,\n \"sensorSamplingAperture.colorSamplingBindingId\"\n ),\n evidence: parseEvidenceList(\n profile.evidence,\n \"sensorSamplingAperture.evidence\"\n ),\n siteCenterLattice,\n geometricSensitiveAperture:\n parseGeometricSensitiveAperture(\n profile.geometricSensitiveAperture,\n \"sensorSamplingAperture.geometricSensitiveAperture\",\n siteCenterLattice\n )\n };\n}\n\nfunction requireSiteIndex(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isSafeInteger(value) ||\n value < 0\n ) {\n throw new InvalidScientificInputError(\n path +\n \" must be a non-negative safe integer color-sampling-site index.\"\n );\n }\n return value;\n}\n\n/**\n * Relative rounding allowance for the lattice and aperture fit tests against the imaging area.\n *\n * The imaging extent (`widthMm · 1000`) and the far aperture edge (first centre + (n − 1)·pitch +\n * offset + width/2) reach the same real number through different chains of at most about eight\n * IEEE-754 double operations, each with a relative rounding error of at most ε/2 of a magnitude no\n * larger than the extent. A geometry that fits exactly can therefore miss by a few units in the last\n * place: a 34-site row of 9.287925696594426 µm sites gives 315.78947368421046 µm of imaging width but\n * a far aperture edge at 315.7894736842105 µm. The fit tests allow 8 ε of the extent (about 1.8e-15\n * relative; 5e-11 µm on a 30 mm sensor), far below any physical aperture difference, and still reject\n * every genuinely oversized lattice or aperture.\n */\nexport const APERTURE_FIT_RELATIVE_TOLERANCE = 8 * Number.EPSILON;\n\n/** The fit-test allowance in micrometres for an imaging extent in micrometres. */\nexport function apertureFitAllowanceMicrometers(extentMicrometers: number): number {\n return APERTURE_FIT_RELATIVE_TOLERANCE * extentMicrometers;\n}\n\nfunction requirePositiveImagingArea(\n imagingArea: SensorImagingArea\n): void {\n requireInputObject(imagingArea, \"imagingArea input\");\n if (\n !Number.isFinite(imagingArea.widthMm) ||\n imagingArea.widthMm <= 0 ||\n !Number.isFinite(imagingArea.heightMm) ||\n imagingArea.heightMm <= 0\n ) {\n throw new InvalidScientificInputError(\n \"imagingArea width/height must be finite and greater than zero.\"\n );\n }\n}\n\n/**\n * Resolves one site's geometric sampling aperture in native sensor physical space.\n *\n * The result is a normalized footprint that averages evenly over its area, for\n * image sampling, plus its physical area and fill fraction. That geometric area\n * is deliberately not treated as light-collection efficiency or as the true\n * photodiode shape.\n */\nexport function resolveSensorSamplingAperture(\n input: ResolveSensorSamplingApertureInput\n): ResolvedSensorSamplingAperture {\n requireInputKeys(input, \"resolveSensorSamplingAperture\", [\"imagingArea\", \"nativeRaster\", \"colorSamplingProfile\", \"colorSamplingBindingProfile\", \"samplingApertureProfile\", \"site\"]);\n requirePositiveImagingArea(\n input.imagingArea\n );\n\n const profile =\n parseSensorSamplingApertureProfile(\n input.samplingApertureProfile\n );\n const binding =\n resolveNativeEffectiveRasterColorSamplingBinding(\n {\n nativeRaster: input.nativeRaster,\n colorSamplingProfile:\n input.colorSamplingProfile,\n bindingProfile:\n input.colorSamplingBindingProfile\n }\n );\n\n if (\n profile.colorSamplingProfileId !==\n binding.colorSamplingProfileId\n ) {\n throw new InvalidScientificInputError(\n \"Sampling-aperture colorSamplingProfileId must match the resolved color-sampling profile.\"\n );\n }\n if (\n profile.colorSamplingBindingId !==\n binding.bindingId\n ) {\n throw new InvalidScientificInputError(\n \"Sampling-aperture colorSamplingBindingId must match the resolved color-sampling binding.\"\n );\n }\n\n if (\n profile.geometricSensitiveAperture.kind ===\n \"unresolved\"\n ) {\n throw new InvalidScientificInputError(\n \"Geometric sensitive aperture is unresolved; a spatial sampling aperture cannot be produced.\"\n );\n }\n\n const siteX = requireSiteIndex(\n input.site.x,\n \"site.x\"\n );\n const siteY = requireSiteIndex(\n input.site.y,\n \"site.y\"\n );\n\n if (\n siteX >=\n binding.colorSamplingSiteGrid.widthSites ||\n siteY >=\n binding.colorSamplingSiteGrid.heightSites\n ) {\n throw new InvalidScientificInputError(\n \"site must lie within the bound color-sampling site grid.\"\n );\n }\n\n const lattice =\n profile.siteCenterLattice;\n const gridWidth =\n binding.colorSamplingSiteGrid.widthSites;\n const gridHeight =\n binding.colorSamplingSiteGrid.heightSites;\n const imagingWidthMicrometers =\n input.imagingArea.widthMm * 1000;\n const imagingHeightMicrometers =\n input.imagingArea.heightMm * 1000;\n\n const lastCenterX =\n lattice\n .firstSiteCenterFromImagingAreaTopLeftMicrometers\n .x +\n (gridWidth - 1) *\n lattice.pitchXMicrometers;\n const lastCenterY =\n lattice\n .firstSiteCenterFromImagingAreaTopLeftMicrometers\n .y +\n (gridHeight - 1) *\n lattice.pitchYMicrometers;\n\n const allowanceX = apertureFitAllowanceMicrometers(\n imagingWidthMicrometers\n );\n const allowanceY = apertureFitAllowanceMicrometers(\n imagingHeightMicrometers\n );\n\n if (\n lastCenterX > imagingWidthMicrometers + allowanceX ||\n lastCenterY > imagingHeightMicrometers + allowanceY\n ) {\n throw new InvalidScientificInputError(\n \"Declared site-center lattice extends beyond the supplied physical imaging area.\"\n );\n }\n\n const aperture =\n profile.geometricSensitiveAperture;\n const apertureOffsetX =\n aperture.centerOffsetFromSiteCenterMicrometers.x;\n const apertureOffsetY =\n aperture.centerOffsetFromSiteCenterMicrometers.y;\n const apertureHalfWidth =\n aperture.widthMicrometers / 2;\n const apertureHalfHeight =\n aperture.heightMicrometers / 2;\n\n const firstApertureLeft =\n lattice.firstSiteCenterFromImagingAreaTopLeftMicrometers.x +\n apertureOffsetX -\n apertureHalfWidth;\n const firstApertureTop =\n lattice.firstSiteCenterFromImagingAreaTopLeftMicrometers.y +\n apertureOffsetY -\n apertureHalfHeight;\n const lastApertureRight =\n lastCenterX +\n apertureOffsetX +\n apertureHalfWidth;\n const lastApertureBottom =\n lastCenterY +\n apertureOffsetY +\n apertureHalfHeight;\n\n if (\n firstApertureLeft < -allowanceX ||\n firstApertureTop < -allowanceY ||\n lastApertureRight >\n imagingWidthMicrometers + allowanceX ||\n lastApertureBottom >\n imagingHeightMicrometers + allowanceY\n ) {\n throw new InvalidScientificInputError(\n \"Declared geometric sensitive aperture does not fit within the supplied physical imaging area across the complete site grid.\"\n );\n }\n\n const siteCenterFromTopLeftX =\n lattice\n .firstSiteCenterFromImagingAreaTopLeftMicrometers\n .x +\n siteX * lattice.pitchXMicrometers;\n const siteCenterFromTopLeftY =\n lattice\n .firstSiteCenterFromImagingAreaTopLeftMicrometers\n .y +\n siteY * lattice.pitchYMicrometers;\n\n const apertureCenterFromTopLeftX =\n siteCenterFromTopLeftX +\n aperture\n .centerOffsetFromSiteCenterMicrometers\n .x;\n const apertureCenterFromTopLeftY =\n siteCenterFromTopLeftY +\n aperture\n .centerOffsetFromSiteCenterMicrometers\n .y;\n const apertureLeftTopX =\n apertureCenterFromTopLeftX -\n aperture.widthMicrometers / 2;\n const apertureRightBottomX =\n apertureCenterFromTopLeftX +\n aperture.widthMicrometers / 2;\n const apertureLeftTopY =\n apertureCenterFromTopLeftY -\n aperture.heightMicrometers / 2;\n const apertureRightBottomY =\n apertureCenterFromTopLeftY +\n aperture.heightMicrometers / 2;\n\n if (\n apertureLeftTopX < -allowanceX ||\n apertureLeftTopY < -allowanceY ||\n apertureRightBottomX >\n imagingWidthMicrometers + allowanceX ||\n apertureRightBottomY >\n imagingHeightMicrometers + allowanceY\n ) {\n throw new InvalidScientificInputError(\n \"Resolved geometric sensitive aperture extends beyond the supplied physical imaging area.\"\n );\n }\n\n const siteCenterFromOpticalAxisMm = {\n x:\n -input.imagingArea.widthMm / 2 +\n siteCenterFromTopLeftX / 1000,\n y:\n -input.imagingArea.heightMm / 2 +\n siteCenterFromTopLeftY / 1000\n };\n const apertureCenterFromOpticalAxisMm = {\n x:\n -input.imagingArea.widthMm / 2 +\n apertureCenterFromTopLeftX / 1000,\n y:\n -input.imagingArea.heightMm / 2 +\n apertureCenterFromTopLeftY / 1000\n };\n const boundsFromOpticalAxisMm = {\n left:\n -input.imagingArea.widthMm / 2 +\n apertureLeftTopX / 1000,\n right:\n -input.imagingArea.widthMm / 2 +\n apertureRightBottomX / 1000,\n top:\n -input.imagingArea.heightMm / 2 +\n apertureLeftTopY / 1000,\n bottom:\n -input.imagingArea.heightMm / 2 +\n apertureRightBottomY / 1000\n };\n\n const areaSquareMicrometers =\n aperture.widthMicrometers *\n aperture.heightMicrometers;\n const nominalCellAreaSquareMicrometers =\n lattice.pitchXMicrometers *\n lattice.pitchYMicrometers;\n const geometricSensitiveAreaFractionOfLatticeCell =\n areaSquareMicrometers /\n nominalCellAreaSquareMicrometers;\n\n if (\n !Number.isFinite(areaSquareMicrometers) ||\n !Number.isFinite(\n nominalCellAreaSquareMicrometers\n ) ||\n !Number.isFinite(\n geometricSensitiveAreaFractionOfLatticeCell\n )\n ) {\n throw new InvalidScientificInputError(\n \"Derived sampling-aperture geometry must remain finite.\"\n );\n }\n\n const channel =\n resolveColorSamplingSite({\n profile: input.colorSamplingProfile,\n site: {\n x: siteX,\n y: siteY\n }\n });\n\n return {\n profileId: profile.profileId,\n colorSamplingProfileId:\n profile.colorSamplingProfileId,\n colorSamplingBindingId:\n profile.colorSamplingBindingId,\n coordinateSystem:\n \"native-sensor-physical\",\n site: {\n x: siteX,\n y: siteY\n },\n channelId: channel.mapping.channelId,\n siteGrid: {\n widthSites: gridWidth,\n heightSites: gridHeight\n },\n lattice: {\n pitchXMicrometers:\n lattice.pitchXMicrometers,\n pitchYMicrometers:\n lattice.pitchYMicrometers,\n firstSiteCenterFromImagingAreaTopLeftMicrometers:\n {\n ...lattice\n .firstSiteCenterFromImagingAreaTopLeftMicrometers\n },\n siteCenterFromImagingAreaTopLeftMicrometers:\n {\n x: siteCenterFromTopLeftX,\n y: siteCenterFromTopLeftY\n },\n siteCenterFromOpticalAxisMm,\n nominalCellAreaSquareMicrometers\n },\n geometricSensitiveAperture: {\n kind:\n \"uniform-axis-aligned-rectangle\",\n widthMicrometers:\n aperture.widthMicrometers,\n heightMicrometers:\n aperture.heightMicrometers,\n centerOffsetFromSiteCenterMicrometers:\n {\n ...aperture\n .centerOffsetFromSiteCenterMicrometers\n },\n centerFromOpticalAxisMm:\n apertureCenterFromOpticalAxisMm,\n boundsFromOpticalAxisMm,\n areaSquareMicrometers,\n geometricSensitiveAreaFractionOfLatticeCell,\n spatialWeighting:\n \"uniform-unit-area-average\",\n neighboringGeometricApertureOverlap:\n \"none-by-model\"\n },\n sitePitchDerivedFromNativeImageRaster:\n false,\n apertureDerivedFromSitePitch: false,\n antiAliasingResponseIncluded: false,\n microlensSpatialRedistributionIncluded:\n false,\n chargeDiffusionIncluded: false,\n electricalCrosstalkIncluded: false,\n spectralResponseIncluded: false,\n quantumEfficiencyIncluded: false,\n opticalThroughputIncluded: false,\n radiometricCollectionAreaEstablished:\n false,\n physicalPhotodiodeGeometryEstablished:\n false,\n provenance: {\n profile: profile.evidence,\n lattice: lattice.evidence,\n aperture: aperture.evidence\n }\n };\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  # Public API reference
2
2
 
3
- Generated from the exact root exports for **@photivra/engine 2.0.0 / root contract 2.0.0** by `node scripts/generate-api-reference.mjs`. No module deep import is supported.
3
+ Generated from the exact root exports for **@photivra/engine 2.2.0 / root contract 2.2.0** by `node scripts/generate-api-reference.mjs`. No module deep import is supported.
4
4
 
5
5
  Use [the developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md) for executable paths and scientific boundaries. Types are contracts, not runtime validation: parse untrusted data, preserve units/reference frames, read assessment blockers, and retain evidence/limitations. Optional properties do not imply a universal default. Model/schema IDs remain independent of the distribution.
6
6
 
@@ -722,6 +722,15 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
722
722
  | [`ImageFormationStageId`](api/core-image-formation.md#imageformationstageid) | Type |
723
723
  | [`ImageFormationTemporalContract`](api/core-image-formation.md#imageformationtemporalcontract) | Type |
724
724
 
725
+ ## core/pixel-limits.ts
726
+
727
+ [Detailed contracts](api/core-pixel-limits.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/core/pixel-limits.ts)
728
+
729
+ | Export | Kind |
730
+ | --- | --- |
731
+ | [`FULL_RESOLUTION_CEILING_PIXELS`](api/core-pixel-limits.md#full_resolution_ceiling_pixels) | Runtime |
732
+ | [`FULL_RESOLUTION_DEFAULT_PIXELS`](api/core-pixel-limits.md#full_resolution_default_pixels) | Runtime |
733
+
725
734
  ## core/scientific-assurance.ts
726
735
 
727
736
  [Detailed contracts](api/core-scientific-assurance.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/core/scientific-assurance.ts)
@@ -1138,12 +1147,14 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
1138
1147
 
1139
1148
  | Export | Kind |
1140
1149
  | --- | --- |
1150
+ | [`SIMULATE_CAPTURE_COST_OPTIONS`](api/facade-simulate-capture.md#simulate_capture_cost_options) | Runtime |
1141
1151
  | [`SIMULATE_CAPTURE_DEFAULT_ILLUMINANCE_LUX`](api/facade-simulate-capture.md#simulate_capture_default_illuminance_lux) | Runtime |
1142
1152
  | [`SIMULATE_CAPTURE_FACADE_VERSION`](api/facade-simulate-capture.md#simulate_capture_facade_version) | Runtime |
1143
1153
  | [`simulateCapture`](api/facade-simulate-capture.md#simulatecapture) | Runtime |
1144
1154
  | [`SimulateCaptureAssumption`](api/facade-simulate-capture.md#simulatecaptureassumption) | Type |
1145
1155
  | [`SimulateCaptureBorderHandling`](api/facade-simulate-capture.md#simulatecaptureborderhandling) | Type |
1146
1156
  | [`SimulateCaptureColorEncoding`](api/facade-simulate-capture.md#simulatecapturecolorencoding) | Type |
1157
+ | [`SimulateCaptureCostOption`](api/facade-simulate-capture.md#simulatecapturecostoption) | Type |
1147
1158
  | [`SimulateCaptureDemosaic`](api/facade-simulate-capture.md#simulatecapturedemosaic) | Type |
1148
1159
  | [`SimulateCaptureExposureMode`](api/facade-simulate-capture.md#simulatecaptureexposuremode) | Type |
1149
1160
  | [`SimulateCaptureLensDistortion`](api/facade-simulate-capture.md#simulatecapturelensdistortion) | Type |
@@ -1152,6 +1163,7 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
1152
1163
  | [`SimulateCaptureOutputFormat`](api/facade-simulate-capture.md#simulatecaptureoutputformat) | Type |
1153
1164
  | [`SimulateCaptureProgress`](api/facade-simulate-capture.md#simulatecaptureprogress) | Type |
1154
1165
  | [`SimulateCaptureResult`](api/facade-simulate-capture.md#simulatecaptureresult) | Type |
1166
+ | [`SimulateCaptureSensorAntiAliasing`](api/facade-simulate-capture.md#simulatecapturesensorantialiasing) | Type |
1155
1167
  | [`SimulateCaptureWhiteBalance`](api/facade-simulate-capture.md#simulatecapturewhitebalance) | Type |
1156
1168
 
1157
1169
  ## gpu/image-kernel-accelerator.ts
@@ -1393,6 +1405,19 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
1393
1405
  | [`DefocusCircle`](api/optics-depth-of-field.md#defocuscircle) | Type |
1394
1406
  | [`DepthOfField`](api/optics-depth-of-field.md#depthoffield) | Type |
1395
1407
 
1408
+ ## optics/diffraction-psf-profile.ts
1409
+
1410
+ [Detailed contracts](api/optics-diffraction-psf-profile.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/optics/diffraction-psf-profile.ts)
1411
+
1412
+ | Export | Kind |
1413
+ | --- | --- |
1414
+ | [`createDiffractionLimitedPsfProfile`](api/optics-diffraction-psf-profile.md#creatediffractionlimitedpsfprofile) | Runtime |
1415
+ | [`CreateDiffractionLimitedPsfProfileInput`](api/optics-diffraction-psf-profile.md#creatediffractionlimitedpsfprofileinput) | Type |
1416
+ | [`DIFFRACTION_LIMITED_PSF_PROFILE_LIMITS`](api/optics-diffraction-psf-profile.md#diffraction_limited_psf_profile_limits) | Runtime |
1417
+ | [`DIFFRACTION_LIMITED_PSF_PROFILE_MODEL`](api/optics-diffraction-psf-profile.md#diffraction_limited_psf_profile_model) | Runtime |
1418
+ | [`DiffractionLimitedPsfProfile`](api/optics-diffraction-psf-profile.md#diffractionlimitedpsfprofile) | Type |
1419
+ | [`DiffractionLimitedPsfWavelength`](api/optics-diffraction-psf-profile.md#diffractionlimitedpsfwavelength) | Type |
1420
+
1396
1421
  ## optics/diffraction.ts
1397
1422
 
1398
1423
  [Detailed contracts](api/optics-diffraction.md) · [Source](https://github.com/Photivra/photivra/blob/main/src/optics/diffraction.ts)
@@ -1929,6 +1954,7 @@ Start here to find a function by task. [Using Photivra from an agent](AGENT_GUID
1929
1954
  | --- | --- |
1930
1955
  | [`createPrintJpegTask`](api/output-print-jpeg.md#createprintjpegtask) | Runtime |
1931
1956
  | [`parsePrintJpegInput`](api/output-print-jpeg.md#parseprintjpeginput) | Runtime |
1957
+ | [`PRINT_JPEG_LIMITS`](api/output-print-jpeg.md#print_jpeg_limits) | Runtime |
1932
1958
  | [`PRINT_JPEG_SCHEMA_VERSION`](api/output-print-jpeg.md#print_jpeg_schema_version) | Runtime |
1933
1959
  | [`PrintJpegInput`](api/output-print-jpeg.md#printjpeginput) | Type |
1934
1960
  | [`PrintJpegOutput`](api/output-print-jpeg.md#printjpegoutput) | Type |