@photivra/engine 2.20.0 → 2.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +178 -1
- package/CITATION.cff +1 -1
- package/README.md +7 -6
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +7 -0
- package/dist/capture/dng-lens-correction-opcodes.d.ts +2 -2
- package/dist/capture/dng-lens-correction-opcodes.js +2 -2
- package/dist/capture/dng-lens-correction-opcodes.js.map +1 -1
- package/dist/capture/exposure-build-up-stage.d.ts +16 -0
- package/dist/capture/exposure-build-up-stage.js +4 -0
- package/dist/capture/exposure-build-up-stage.js.map +1 -0
- package/dist/capture/native-environment-lean.d.ts +2 -1
- package/dist/capture/native-environment-lean.js +41 -73
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-environment-tabulated.js +4 -3
- package/dist/capture/native-environment-tabulated.js.map +1 -1
- package/dist/capture/native-raw.d.ts +3 -2
- package/dist/capture/native-raw.js +5 -4
- package/dist/capture/native-raw.js.map +1 -1
- package/dist/capture/sensor-raw-producer.d.ts +4 -1
- package/dist/capture/sensor-raw-producer.js +12 -3
- package/dist/capture/sensor-raw-producer.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/equipment/generic-lens-catalogue.d.ts +3 -2
- package/dist/equipment/generic-lens-catalogue.js +18 -5
- package/dist/equipment/generic-lens-catalogue.js.map +1 -1
- package/dist/equipment/generic-tier-assets.d.ts +32 -0
- package/dist/equipment/generic-tier-assets.js +16 -11
- package/dist/equipment/generic-tier-assets.js.map +1 -1
- package/dist/equipment/sensor-profile-body.d.ts +78 -0
- package/dist/equipment/sensor-profile-body.js +77 -0
- package/dist/equipment/sensor-profile-body.js.map +1 -0
- package/dist/equipment/sensor-profiles.d.ts +8 -0
- package/dist/equipment/sensor-profiles.js +82 -0
- package/dist/equipment/sensor-profiles.js.map +1 -0
- package/dist/facade/catalogue-lens-signal.d.ts +2 -2
- package/dist/facade/catalogue-lens-signal.js +58 -71
- package/dist/facade/catalogue-lens-signal.js.map +1 -1
- package/dist/facade/chart-radiance-batch.js +2 -1
- package/dist/facade/chart-radiance-batch.js.map +1 -1
- package/dist/facade/defocus-image-space-provider.d.ts +7 -0
- package/dist/facade/defocus-image-space-provider.js +64 -76
- package/dist/facade/defocus-image-space-provider.js.map +1 -1
- package/dist/facade/display-view-gpu-session.js +2 -0
- package/dist/facade/display-view-gpu-session.js.map +1 -1
- package/dist/facade/display-view-gpu.d.ts +6 -1
- package/dist/facade/display-view-gpu.js.map +1 -1
- package/dist/facade/display-view-lens-signal.js +25 -23
- package/dist/facade/display-view-lens-signal.js.map +1 -1
- package/dist/facade/display-view.js +5 -23
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/expected-signal-setup.d.ts +3 -1
- package/dist/facade/expected-signal-setup.js +1 -1
- package/dist/facade/expected-signal-setup.js.map +1 -1
- package/dist/facade/expected-signal.d.ts +47 -14
- package/dist/facade/expected-signal.js +117 -112
- package/dist/facade/expected-signal.js.map +1 -1
- package/dist/facade/exposure-build-up.d.ts +70 -0
- package/dist/facade/exposure-build-up.js +164 -0
- package/dist/facade/exposure-build-up.js.map +1 -0
- package/dist/facade/fast-methods.js +9 -1
- package/dist/facade/fast-methods.js.map +1 -1
- package/dist/facade/generic-lens-capture.d.ts +2 -2
- package/dist/facade/generic-lens-capture.js +2 -2
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/image-plane-enable.d.ts +7 -0
- package/dist/facade/image-plane-enable.js +17 -0
- package/dist/facade/image-plane-enable.js.map +1 -0
- package/dist/facade/image-plane-lattice-data.d.ts +6 -0
- package/dist/facade/image-plane-lattice-data.js +10 -0
- package/dist/facade/image-plane-lattice-data.js.map +1 -0
- package/dist/facade/image-plane-support.d.ts +33 -0
- package/dist/facade/image-plane-support.js +11 -0
- package/dist/facade/image-plane-support.js.map +1 -0
- package/dist/facade/image-plane.d.ts +36 -0
- package/dist/facade/image-plane.js +353 -0
- package/dist/facade/image-plane.js.map +1 -0
- package/dist/facade/mixed-illumination.d.ts +108 -0
- package/dist/facade/mixed-illumination.js +174 -0
- package/dist/facade/mixed-illumination.js.map +1 -0
- package/dist/facade/representative-light-sources.d.ts +72 -0
- package/dist/facade/representative-light-sources.js +124 -0
- package/dist/facade/representative-light-sources.js.map +1 -0
- package/dist/facade/scene-radiance.d.ts +129 -4
- package/dist/facade/scene-radiance.js +48 -13
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +39 -10
- package/dist/facade/simulate-capture.js +252 -92
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.js +14 -6
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.d.ts +13 -1
- package/dist/gpu/chart-composite-gpu.js +48 -9
- package/dist/gpu/chart-composite-gpu.js.map +1 -1
- package/dist/gpu/chart-radiance-gpu.js +4 -30
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/gpu/display-view-composite-material-module.d.ts +10 -4
- package/dist/gpu/display-view-composite-material-module.js +39 -13
- package/dist/gpu/display-view-composite-material-module.js.map +1 -1
- package/dist/gpu/display-view-image-material-module.d.ts +86 -0
- package/dist/gpu/display-view-image-material-module.js +339 -0
- package/dist/gpu/display-view-image-material-module.js.map +1 -0
- package/dist/gpu/display-view-image-quality.d.ts +45 -0
- package/dist/gpu/display-view-image-quality.js +380 -0
- package/dist/gpu/display-view-image-quality.js.map +1 -0
- package/dist/gpu/display-view-quality-gpu.d.ts +67 -1
- package/dist/gpu/display-view-quality-gpu.js +136 -205
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.d.ts +51 -3
- package/dist/gpu/display-view-speed-gpu.js +131 -93
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +29 -15
- package/dist/gpu/wgsl-display-view-quality-kernel.js +58 -36
- package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +21 -6
- package/dist/gpu/wgsl-display-view-speed-kernel.js +46 -11
- package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
- package/dist/gpu/wgsl-exact-sum.d.ts +20 -0
- package/dist/gpu/wgsl-exact-sum.js +42 -0
- package/dist/gpu/wgsl-exact-sum.js.map +1 -0
- package/dist/index.d.ts +11 -3
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/motion/subject-motion.d.ts +66 -0
- package/dist/motion/subject-motion.js +52 -0
- package/dist/motion/subject-motion.js.map +1 -0
- package/dist/optics/generic-lens-lateral-color.d.ts +83 -0
- package/dist/optics/generic-lens-lateral-color.js +77 -0
- package/dist/optics/generic-lens-lateral-color.js.map +1 -0
- package/dist/optics/generic-lens-psf.js +54 -46
- package/dist/optics/generic-lens-psf.js.map +1 -1
- package/dist/optics/lens-psf-profile.d.ts +7 -0
- package/dist/optics/lens-psf-profile.js +2 -1
- package/dist/optics/lens-psf-profile.js.map +1 -1
- package/dist/output/developed-lens-corrections.d.ts +19 -5
- package/dist/output/developed-lens-corrections.js +28 -9
- package/dist/output/developed-lens-corrections.js.map +1 -1
- package/dist/output/generic-lens-corrections.d.ts +41 -5
- package/dist/output/generic-lens-corrections.js +52 -8
- package/dist/output/generic-lens-corrections.js.map +1 -1
- package/dist/output/print-plan.d.ts +41 -5
- package/dist/output/print-plan.js +59 -14
- package/dist/output/print-plan.js.map +1 -1
- package/dist/sensor/binomial-sample.d.ts +3 -0
- package/dist/sensor/binomial-sample.js +86 -0
- package/dist/sensor/binomial-sample.js.map +1 -0
- package/dist/sensor/sensor-characteristics.d.ts +10 -0
- package/dist/sensor/sensor-characteristics.js +20 -9
- package/dist/sensor/sensor-characteristics.js.map +1 -1
- package/docs/AGENT_GUIDE.md +1 -0
- package/docs/API_REFERENCE.md +98 -1
- package/docs/QUICK_START.md +125 -0
- package/docs/USAGE.md +92 -1
- package/docs/api/core-version.md +1 -1
- package/docs/api/equipment-generic-lens-catalogue.md +10 -5
- package/docs/api/equipment-sensor-profile-body.md +64 -0
- package/docs/api/equipment-sensor-profiles.md +86 -0
- package/docs/api/exports.json +207 -2
- package/docs/api/facade-exposure-build-up.md +105 -0
- package/docs/api/facade-fast-methods.md +9 -1
- package/docs/api/facade-image-plane-enable.md +16 -0
- package/docs/api/facade-mixed-illumination.md +67 -0
- package/docs/api/facade-representative-light-sources.md +131 -0
- package/docs/api/facade-scene-radiance.md +54 -3
- package/docs/api/facade-simulate-capture.md +26 -6
- package/docs/api/motion-subject-motion.md +23 -0
- package/docs/api/optics-generic-lens-lateral-color.md +79 -0
- package/docs/api/output-developed-lens-corrections.md +10 -1
- package/docs/api/output-generic-lens-corrections.md +40 -4
- package/docs/api/output-print-plan.md +35 -1
- package/llms.txt +2 -0
- package/package.json +1 -1
|
@@ -965,58 +965,21 @@ function sensorMatches(site, photo, x, y, t, memo) {
|
|
|
965
965
|
return sameRecordExcept(photo, t.photo, PHOTO_SITE_FIELDS, memo) && siteSlot(photo.site, x, y) &&
|
|
966
966
|
photo.temporalSamples.length === t.photo.temporalSamples.length;
|
|
967
967
|
}
|
|
968
|
-
/** The sensor stage of calculateNativeRawSite, in the same operation order. Returns undefined when one of its checks would throw. */
|
|
969
968
|
/**
|
|
970
|
-
* #418: the charge and read-noise streams of the site
|
|
969
|
+
* #418: the charge and read-noise streams of the site flatSensorSite is computing, reseeded for each site. flatSensorSite is
|
|
971
970
|
* synchronous and never re-entered, so one pair serves every call; reseeding sets exactly the state a new
|
|
972
971
|
* createDeterministicUniformStream would start from, so every draw is unchanged.
|
|
973
972
|
*/
|
|
974
973
|
const chargeStream = createResettableUniformStream(), readNoiseStream = createResettableUniformStream();
|
|
975
|
-
function
|
|
976
|
-
const ratio = h.total / t.capacity, headroom = t.capacity - h.total;
|
|
977
|
-
if (!Number.isFinite(ratio) || !Number.isFinite(headroom))
|
|
978
|
-
return undefined;
|
|
979
|
-
const pattern = t.pattern === undefined ? null : evaluateParsedFixedPatternSite(t.pattern, { x: h.x, y: h.y });
|
|
980
|
-
const photoE = h.photo.expectedGeneratedElectronCount;
|
|
981
|
-
const photoMean = pattern === null ? photoE : photoE * pattern.photoResponseGainFactor;
|
|
982
|
-
const darkMean = pattern === null ? h.darkE : h.darkE * pattern.darkCurrentFactor;
|
|
983
|
-
if (!Number.isFinite(photoMean) || photoMean < 0 || !Number.isFinite(darkMean) || darkMean < 0)
|
|
984
|
-
return undefined;
|
|
985
|
-
const random = chargeStream;
|
|
986
|
-
random.reset(deriveNativeSiteStreamSeedUint32(seed, index, NATIVE_SITE_CHARGE_STREAM_ID));
|
|
987
|
-
const photoRealized = samplePoisson(photoMean, random), darkRealized = samplePoisson(darkMean, random);
|
|
988
|
-
const realized = photoRealized + darkRealized + 0;
|
|
989
|
-
if (!Number.isFinite(realized) || realized < 0)
|
|
990
|
-
return undefined;
|
|
991
|
-
const readRandom = readNoiseStream;
|
|
992
|
-
readRandom.reset(deriveNativeSiteStreamSeedUint32(seed, index, NATIVE_SITE_READ_NOISE_STREAM_ID));
|
|
993
|
-
const regime = t.readout.regime, capacity = t.capacity;
|
|
994
|
-
const afterPhysical = Math.min(realized, capacity), physicalSaturation = afterPhysical < realized;
|
|
995
|
-
// The components' draws and their sum in one loop: the same draws, added to 0 in the same order as before (#418).
|
|
996
|
-
const components = regime.readNoiseComponents;
|
|
997
|
-
let totalReadNoise = 0;
|
|
998
|
-
for (let k = 0; k < components.length; k++) {
|
|
999
|
-
const rms = components[k].rmsElectrons.value;
|
|
1000
|
-
totalReadNoise = totalReadNoise + (rms === 0 ? 0 : sampleDeterministicStandardNormal(readRandom) * rms);
|
|
1001
|
-
}
|
|
1002
|
-
const afterReadNoise = afterPhysical + totalReadNoise + (pattern === null ? 0 : pattern.readoutOffsetElectrons);
|
|
1003
|
-
const threshold = regime.preAdcSaturationElectronEquivalent.value;
|
|
1004
|
-
const afterPreAdc = Math.min(afterReadNoise, threshold), preAdcSaturation = afterReadNoise > threshold;
|
|
1005
|
-
const quantized = adcTransfer(regime, t.readout.adcMaximumCode, afterPreAdc).quantized;
|
|
1006
|
-
const digitalSaturationCode = regime.adc.digitalSaturationCode;
|
|
1007
|
-
return { rawCode: Math.max(0, Math.min(quantized, digitalSaturationCode)), blackLevelCode: regime.adc.blackLevelCode, digitalSaturationCode,
|
|
1008
|
-
flags: Number(physicalSaturation) | Number(preAdcSaturation) << 1 | Number(quantized >= digitalSaturationCode) << 2,
|
|
1009
|
-
whiteCode: t.whiteCode, photoRealized, darkRealized };
|
|
1010
|
-
}
|
|
1011
|
-
function flatSensorStage(t) {
|
|
974
|
+
function flatSensorStage(t, b) {
|
|
1012
975
|
const regime = t.readout.regime;
|
|
1013
976
|
return { darkRate: t.darkRate, capacity: t.capacity, pattern: t.pattern, whiteCode: t.whiteCode, regime, adcMaximumCode: t.readout.adcMaximumCode,
|
|
1014
977
|
inlDefined: regime.adc.integralNonLinearity !== undefined, gain: regime.systemConversionGainElectronsPerCode.value, black: regime.adc.blackLevelCode,
|
|
1015
978
|
digitalGain: regime.adc.digitalGain, digitalSaturationCode: regime.adc.digitalSaturationCode, threshold: regime.preAdcSaturationElectronEquivalent.value,
|
|
1016
979
|
rms: Float64Array.from(regime.readNoiseComponents, (component) => component.rmsElectrons.value), darkMean: NaN, darkThreshold: NaN,
|
|
1017
|
-
out: { rawCode: 0, blackLevelCode: 0, digitalSaturationCode: 0, flags: 0, whiteCode: 0 } };
|
|
980
|
+
out: { rawCode: 0, blackLevelCode: 0, digitalSaturationCode: 0, flags: 0, whiteCode: 0, photoRealized: 0, darkRealized: 0 }, b };
|
|
1018
981
|
}
|
|
1019
|
-
/** Writes the site's outputs into `f.out`; false where
|
|
982
|
+
/** Writes the site's outputs into `f.out`; false where a check of calculateNativeRawSite would throw. */
|
|
1020
983
|
function flatSensorSite(f, photoE, darkE, total, x, y, index, seed) {
|
|
1021
984
|
const ratio = total / f.capacity, headroom = f.capacity - total;
|
|
1022
985
|
if (!Number.isFinite(ratio) || !Number.isFinite(headroom))
|
|
@@ -1028,8 +991,7 @@ function flatSensorSite(f, photoE, darkE, total, x, y, index, seed) {
|
|
|
1028
991
|
return false;
|
|
1029
992
|
const random = chargeStream;
|
|
1030
993
|
random.reset(deriveNativeSiteStreamSeedUint32(seed, index, NATIVE_SITE_CHARGE_STREAM_ID));
|
|
1031
|
-
|
|
1032
|
-
let darkRealized;
|
|
994
|
+
let photoRealized = samplePoisson(photoMean, random), darkRealized;
|
|
1033
995
|
if (darkMean > 0 && darkMean < 30) {
|
|
1034
996
|
// samplePoisson's branch for 0 < mean < 30 (Knuth's product of uniforms) with its threshold Math.exp(−mean) kept while the
|
|
1035
997
|
// mean repeats: the same draws from the same stream. (createPoissonSampler would also do this, but it brings the
|
|
@@ -1048,11 +1010,17 @@ function flatSensorSite(f, photoE, darkE, total, x, y, index, seed) {
|
|
|
1048
1010
|
}
|
|
1049
1011
|
else
|
|
1050
1012
|
darkRealized = samplePoisson(darkMean, random);
|
|
1013
|
+
const b = f.b;
|
|
1014
|
+
if (b) {
|
|
1015
|
+
b.split(index, photoMean, darkMean, photoRealized, darkRealized);
|
|
1016
|
+
photoRealized = b.photo;
|
|
1017
|
+
darkRealized = b.dark;
|
|
1018
|
+
}
|
|
1051
1019
|
const realized = photoRealized + darkRealized + 0;
|
|
1052
1020
|
if (!Number.isFinite(realized) || realized < 0)
|
|
1053
1021
|
return false;
|
|
1054
1022
|
const readRandom = readNoiseStream;
|
|
1055
|
-
readRandom.reset(deriveNativeSiteStreamSeedUint32(seed, index, NATIVE_SITE_READ_NOISE_STREAM_ID));
|
|
1023
|
+
readRandom.reset(deriveNativeSiteStreamSeedUint32(seed, index, b ? b.read : NATIVE_SITE_READ_NOISE_STREAM_ID));
|
|
1056
1024
|
const capacity = f.capacity;
|
|
1057
1025
|
const afterPhysical = Math.min(realized, capacity), physicalSaturation = afterPhysical < realized;
|
|
1058
1026
|
const rmsAll = f.rms;
|
|
@@ -1084,6 +1052,8 @@ function flatSensorSite(f, photoE, darkE, total, x, y, index, seed) {
|
|
|
1084
1052
|
out.digitalSaturationCode = digitalSaturationCode;
|
|
1085
1053
|
out.flags = Number(physicalSaturation) | Number(preAdcSaturation) << 1 | Number(quantized >= digitalSaturationCode) << 2;
|
|
1086
1054
|
out.whiteCode = f.whiteCode;
|
|
1055
|
+
out.photoRealized = photoRealized;
|
|
1056
|
+
out.darkRealized = darkRealized;
|
|
1087
1057
|
return true;
|
|
1088
1058
|
}
|
|
1089
1059
|
/** The Kahan (compensated) total that composeSensorAccumulatedCharge computes, for photo and dark charge only. */
|
|
@@ -1096,28 +1066,32 @@ function chargeTotal(photoE, darkE) {
|
|
|
1096
1066
|
}
|
|
1097
1067
|
return sum;
|
|
1098
1068
|
}
|
|
1069
|
+
/**
|
|
1070
|
+
* True when the flat stage `f` reproduces the fully computed site `result` bit for bit: its dark and total charge, both charge
|
|
1071
|
+
* realizations, its codes and its flags.
|
|
1072
|
+
*/
|
|
1073
|
+
function reproducesSite(f, parsed, result, photo, x, y, index, seed) {
|
|
1074
|
+
const darkE = f.darkRate * photo.localExposureDurationSeconds, total = chargeTotal(photo.expectedGeneratedElectronCount, darkE);
|
|
1075
|
+
const r = result.readout.value, realization = result.realization.value, out = f.out;
|
|
1076
|
+
return flatSensorSite(f, photo.expectedGeneratedElectronCount, darkE, total, x, y, index, seed) && Object.is(darkE, parsed.charge.darkCharge.expectedDarkElectronCount) &&
|
|
1077
|
+
Object.is(total, result.accumulatedCharge.value.totalExpectedStoredElectronCount) &&
|
|
1078
|
+
Object.is(out.photoRealized, realization.photoRealizedElectronCount) && Object.is(out.darkRealized, realization.darkRealizedElectronCount) &&
|
|
1079
|
+
realization.additionalComponents.length === 0 && out.rawCode === r.rawCode && out.blackLevelCode === r.blackLevelCode && out.digitalSaturationCode === r.digitalSaturationCode &&
|
|
1080
|
+
out.flags === (Number(r.physicalScalarSaturationApplied) | Number(r.preAdcSaturationApplied) << 1 | Number(r.digitalSaturationApplied) << 2);
|
|
1081
|
+
}
|
|
1099
1082
|
/**
|
|
1100
1083
|
* #394: a sensor template from one fully parsed and computed site (`calculateNativeRawSite`), as the lean sensor stage builds
|
|
1101
1084
|
* its templates; undefined unless the lean arithmetic reproduces that site's dark and total charge, both charge realizations,
|
|
1102
1085
|
* its codes and its flags bit for bit. Its `compute` then gives `calculateNativeRawSite`'s outputs for any site of the same
|
|
1103
1086
|
* readout inputs (same CFA channel, dark current, capacity, readout regime and fixed-pattern profile).
|
|
1104
1087
|
*/
|
|
1105
|
-
export function createVerifiedNativeSiteReadout(parsed, result, whiteCode, photo, x, y, index, seed) {
|
|
1088
|
+
export function createVerifiedNativeSiteReadout(parsed, result, whiteCode, photo, x, y, index, seed, b) {
|
|
1106
1089
|
try {
|
|
1107
1090
|
const readout = resolveSensorReadoutRegime({ profile: parsed.readoutProfile, regimeId: parsed.regimeId });
|
|
1108
1091
|
const t = { darkRate: parsed.charge.darkCharge.darkCurrentElectronsPerSecond,
|
|
1109
1092
|
capacity: result.capacity.value.physicalChargeCapacityElectrons, readout, pattern: parsed.fixedPatternNoise, whiteCode };
|
|
1110
|
-
const
|
|
1111
|
-
|
|
1112
|
-
if (!out || !Object.is(darkE, parsed.charge.darkCharge.expectedDarkElectronCount) || !Object.is(total, result.accumulatedCharge.value.totalExpectedStoredElectronCount) ||
|
|
1113
|
-
!Object.is(out.photoRealized, realization.photoRealizedElectronCount) || !Object.is(out.darkRealized, realization.darkRealizedElectronCount) ||
|
|
1114
|
-
realization.additionalComponents.length !== 0 || out.rawCode !== r.rawCode || out.blackLevelCode !== r.blackLevelCode || out.digitalSaturationCode !== r.digitalSaturationCode ||
|
|
1115
|
-
out.flags !== (Number(r.physicalScalarSaturationApplied) | Number(r.preAdcSaturationApplied) << 1 | Number(r.digitalSaturationApplied) << 2))
|
|
1116
|
-
return undefined;
|
|
1117
|
-
// #449: the flat stage must reproduce the verification site too.
|
|
1118
|
-
const flat = flatSensorStage(t), fo = flat.out;
|
|
1119
|
-
if (!flatSensorSite(flat, photo.expectedGeneratedElectronCount, darkE, total, x, y, index, seed) || fo.rawCode !== out.rawCode || fo.blackLevelCode !== out.blackLevelCode ||
|
|
1120
|
-
fo.digitalSaturationCode !== out.digitalSaturationCode || fo.flags !== out.flags || fo.whiteCode !== out.whiteCode)
|
|
1093
|
+
const flat = flatSensorStage(t, b), fo = flat.out;
|
|
1094
|
+
if (!reproducesSite(flat, parsed, result, photo, x, y, index, seed))
|
|
1121
1095
|
return undefined;
|
|
1122
1096
|
return {
|
|
1123
1097
|
compute(photoE, duration, sx, sy, siteIndex, siteSeed) {
|
|
@@ -1189,20 +1163,21 @@ export function createNativeEnvironmentSensorLean(frame, producerFrame, nativeWi
|
|
|
1189
1163
|
claim(site) {
|
|
1190
1164
|
return typeof site === "object" && site !== null && handles.has(site) ? site : undefined;
|
|
1191
1165
|
},
|
|
1192
|
-
compute(handle, index, seed, timing) {
|
|
1193
|
-
|
|
1194
|
-
|
|
1166
|
+
compute(handle, index, seed, timing, b) {
|
|
1167
|
+
// The template's flat stage (made in observe(), with the same build-up stage); the caller copies the outputs at once.
|
|
1168
|
+
const h = handles.get(handle), f = h.template.flat;
|
|
1169
|
+
if (flatSensorSite(f, h.photo.expectedGeneratedElectronCount, h.darkE, h.total, h.x, h.y, index, seed)) {
|
|
1195
1170
|
nativeEnvironmentLeanStatistics.sensorSites++;
|
|
1196
|
-
|
|
1197
|
-
|
|
1171
|
+
return f.out;
|
|
1172
|
+
}
|
|
1198
1173
|
// A compute-phase check failed: the full path computes (and throws) exactly as it would have.
|
|
1199
1174
|
const parsed = parseNativeRawProducerSite(composeNativeEnvironmentSensorSite(h.site, h.photo), index, producerFrame, timing);
|
|
1200
|
-
const r = calculateNativeRawSite(parsed, seed, index).readout.value;
|
|
1175
|
+
const r = calculateNativeRawSite(parsed, seed, index, b).readout.value;
|
|
1201
1176
|
return { rawCode: r.rawCode, blackLevelCode: r.blackLevelCode, digitalSaturationCode: r.digitalSaturationCode,
|
|
1202
1177
|
flags: Number(r.physicalScalarSaturationApplied) | Number(r.preAdcSaturationApplied) << 1 | Number(r.digitalSaturationApplied) << 2,
|
|
1203
1178
|
whiteCode: calculateSiteEffectiveSaturationCode(r, parsed.readoutProfile, parsed.regimeId) };
|
|
1204
1179
|
},
|
|
1205
|
-
observe(index, parsed, result, whiteCode, seed) {
|
|
1180
|
+
observe(index, parsed, result, whiteCode, seed, b) {
|
|
1206
1181
|
const entry = pending.get(index);
|
|
1207
1182
|
pending.delete(index);
|
|
1208
1183
|
if (!entry || templates.length >= MAXIMUM_TEMPLATES)
|
|
@@ -1215,18 +1190,11 @@ export function createNativeEnvironmentSensorLean(frame, producerFrame, nativeWi
|
|
|
1215
1190
|
const t = { site, photo, phase, x, y, verified: false, darkRate: parsed.charge.darkCharge.darkCurrentElectronsPerSecond,
|
|
1216
1191
|
capacity: result.capacity.value.physicalChargeCapacityElectrons, readout, pattern: parsed.fixedPatternNoise, whiteCode };
|
|
1217
1192
|
templates.push(t);
|
|
1218
|
-
// Self-check: the template matches itself and
|
|
1193
|
+
// Self-check: the template matches itself and its flat stage reproduces its full computation bit for bit.
|
|
1219
1194
|
if (!sensorMatches(site, photo, x, y, t, new WeakMap()))
|
|
1220
1195
|
return;
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
const out = leanSensorSite(t, { photo, darkE, total, x, y }, index, seed);
|
|
1224
|
-
if (!out || !Object.is(darkE, parsed.charge.darkCharge.expectedDarkElectronCount) ||
|
|
1225
|
-
!Object.is(total, result.accumulatedCharge.value.totalExpectedStoredElectronCount) ||
|
|
1226
|
-
!Object.is(out.photoRealized, realization.photoRealizedElectronCount) || !Object.is(out.darkRealized, realization.darkRealizedElectronCount) ||
|
|
1227
|
-
realization.additionalComponents.length !== 0 || out.rawCode !== r.rawCode || out.blackLevelCode !== r.blackLevelCode ||
|
|
1228
|
-
out.digitalSaturationCode !== r.digitalSaturationCode || out.flags !== (Number(r.physicalScalarSaturationApplied) |
|
|
1229
|
-
Number(r.preAdcSaturationApplied) << 1 | Number(r.digitalSaturationApplied) << 2))
|
|
1196
|
+
t.flat = flatSensorStage(t, b);
|
|
1197
|
+
if (!reproducesSite(t.flat, parsed, result, photo, x, y, index, seed))
|
|
1230
1198
|
return;
|
|
1231
1199
|
t.verified = true;
|
|
1232
1200
|
}
|