# 像元级科学相机模型 `dist/camera.js` 提供无依赖 ES module。它以实际 ADU 像元阵列生成相机帧;屏幕图像、测光和 CSV 均使用同一份采样结果。没有“冷却条件合格才画亮点”的显示判据:只要上游模型给出散射光电子,宽而暗的热离子也会进入图像。 ## 调用合同 ```js import { simulateCameraFrame, cameraConfigFromMetrics, renderFrame, aperturePhotometry, frameToCSV, } from './camera.js'; const cfg = cameraConfigFromMetrics(params, metrics, env, frameIndex); // 可选:有限增益的前两矩近似,避免低倍增增益时直接套用高增益极限。 cfg.emModel = 'finiteGainGamma'; const frame = simulateCameraFrame(cfg); const display = renderFrame(canvas, frame, { autoscale: true, colorMap: 'violet', saturationColor: true, }); const measurements = aperturePhotometry(frame, { radiusPx: 4 }); const csv = frameToCSV(frame); ``` 缓存一帧至下次曝光完成再替换。界面重绘与改窗口尺寸不应重采样;暂停时保持 seed 和帧不变。相同参数及 seed 返回逐像元相同结果,改变 seed 才得到另一帧的光子涨落。实际浏览器采集频率建议上限 5–8 帧/秒,曝光时间决定单帧计数;这只是显示刷新节流,不改变每帧的物理曝光。 直接调用的主要参数: | 参数 | 单位 / 意义 | 默认 | |---|---|---| | `width`, `height` | 实际模拟传感器 / ROI 的像元数;不是显示画布尺寸 | 128 × 96 | | `pixelSizeUm` | 传感器物理像元边长,µm | 16 | | `magnification` | 总成像放大率 | 20 | | `ions[].xUm`, `ions[].yUm` | 相对于视场中心的物方位置,µm;y 随画布向下 | 0 | | `ions[].photonsElectrons` | **本次曝光、整张 PSF 的平均光电子数,已含光路损耗和 QE** | 0 | | `sigmaObjectUm` 或 `sigmaXUm`, `sigmaYUm` | 未做像元积分的物方高斯 PSF 标准差,µm | 0.5 | | `ions[].sigmaXUm`, `sigmaYUm` | 可为每个离子覆盖 PSF 宽度 | 使用全局 | | `backgroundElectronsPerPixel` | 本次曝光每像元杂散背景的平均光电子数 | 0.05 | | `darkRateEPS` | 每像元每秒暗电子数 | 0.001 | | `cicElectronsPerPixel` | 每次读出每像元有效输入端 CIC 电子均值 | 0 | | `exposureMs` | 曝光时间,ms;用于暗电流积分 | 20 | | `emGain` | 平均倍增增益;1 表示关闭 EM | 1 | | `emModel` | `highGainGamma` 或 `finiteGainGamma` | `highGainGamma` | | `readNoiseElectrons` | **EM 寄存器之后**的输出端读噪,电子 RMS | 35 | | `fullWellElectrons` | 传感器像元输入端满阱,电子 | 80,000 | | `emFullWellElectrons` | EM 输出寄存器满阱,电子 | 800,000 | | `offsetADU` | 加在 ADC 上的电子学基线,ADU | 100 | | `conversionGainElectronsPerADU` | 输出端电子 / ADU;必须与读出模式匹配 | 1 | | `bitDepth` | ADC 位深,1–24;≤16 时返回 `Uint16Array` | 16 | | `seed` | 无符号 32 位随机种子 | 1 | `photonsElectrons` 与 `backgroundElectronsPerPixel` 已按本次曝光积分。改变 `exposureMs` 时,直接调用者必须按曝光重新给出这两者,不能重复乘曝光;`cameraConfigFromMetrics` 从上游 `photonsPerIon` 获取积分后的数值。 适配函数读取 `physicalImageSigmaXUm/YUm`,其次读取 `physicalImageSigmaUm`。这些宽度必须包含衍射、热运动及离焦,但**不包含像元采样展宽**。只有旧标量接口缺失时,才用 `imageSigmaUm² − pixelObjectUm² / 12` 回推物理宽度。`metrics.photonsPerIon` 直接作为光电子数使用,不再乘 QE。 物方像元 `p = pixelSizeUm / magnification`;视场严格为 `width × p` 和 `height × p`。`centersPx` 中的坐标使用像元边界为整数、中心为 `x + 0.5` 的约定。因此传感器正中心是 `(width / 2, height / 2)`。离子落在视场外的信号保持丢失,不把截断 PSF 重新归一化。 ## 光学、光子与读出模型 每个离子的二维高斯 PSF 按像元边界用 erf 差分积分: `μxy = Ne × [Φ(x1) − Φ(x0)] × [Φ(y1) − Φ(y0)]`。 这消除了点采样高斯在欠采样、亚像元位移时产生的虚假计数变化。erf 采用最大绝对误差约 1.5 × 10⁻⁷ 的近似;积分形式对所选高斯 PSF 是解析的。PSF 是真实 Airy 图案的近轴高斯近似,未声称精确模拟 Airy 环、像差或偶极方向图;其输入展宽和收光率应由上游光学模型给出。 光电子、杂散背景、暗电流和等效输入 CIC 分别做 Poisson 采样。低计数使用整数乘积算法,大计数采用 PTRS 整数拒绝采样,不以画面纹理代替噪声,也不用会产生负光子数的高斯近似替代 Poisson。 输入电子先经像元满阱裁切,然后进入 EM: - 关闭 EM:输出电子数等于输入电子数。 - 高增益模型:给定输入电子 `n`,输出为 `Gamma(shape=n, scale=g)`;这是高增益极限,其均值 `ng`、条件方差 `ng²`,总计数方差对应 `F²≈2`。 - 可选有限增益模型:`Gamma(shape=n g/(g−1), scale=g−1)`。保持均值 `ng`,条件方差 `ng(g−1)`,因此复合 Poisson 总方差对应 `F²=2−1/g`。此选项只匹配有限增益级联的前两矩,并非对真实离散级联分布的精确求解;尤其不能当作单电子概率直方图标定模型。 EM 输出再经独立寄存器满阱裁切,加入 Gaussian 读噪,然后按输出电子 / ADU 转换,增加基线、四舍五入并按 ADC 位深裁切。`saturationFlags` 中 bit 1、2、4 分别标记输入满阱、EM 寄存器满阱及 ADC 饱和;可以同时出现。基线也会占用 ADC 正向余量。低于 0 ADU 的信号会裁切;若基线设得太低,读噪均值会受截断偏置,必须调高基线后再做测光。 EM 降低输入折算读噪 `RN/g`,不能增加已经收集到的光子数,也不能提高纯光子散粒噪声极限。在高增益近似下,SNR 分母为: `sqrt[ F² (S + nPix B) + nPix (RN/g)² + nPix (c/g)²/12 ]`。 这里 `c` 是输出端电子 / ADU。最后一项是 ADC 四舍五入误差在输入端的**均匀量化近似**,标准差为 `c/(g√12)`,不乘 EM 额外噪声因子。相机 SNR、实测口径噪声及期望口径噪声均含该项;用环形背景时,背景均值估计的不确定度也包含环内量化噪声。`aperturePhotometry` 返回 `quantizationNoiseInputElectronsPerPixel` 供查看该预算。 该近似适用于模拟信号或其他噪声足以跨越 ADC 码阶的情况,**不适合极粗 ADC 或缺少抖动的低计数信号**:此时舍入误差与信号相关,可能产生偏置、死区或离散分布。量化噪声预算不能纠正这些偏置,应使用更细转换增益、保留足够偏置并比较实际原始 ADU。相反,在无读噪、恰好与整数电子对齐的 ADC 中,均匀噪声项可能过于保守。原始帧始终按真实码阶直接四舍五入采样,并未额外向像元注入一份虚构的均匀噪声。 该公式与实验装置的具体传感器标定无关;默认满阱、暗电流、CIC 与 ADU 转换只用于教学,不代表某个相机型号的校准证书。 ## 返回数据、测光与显示 `frame.adu` 为真实采样的原始 ADU。`expectedElectrons` 为信号加全部背景的平均输入电子;`signalExpectedElectrons` 只含信号;`inputElectrons` 是满阱裁切前的实际采样输入电子。后两者和 `expectedElectrons` 是**仿真真值**,应在学生界面中如此标注,不应与实际相机可直接测量的数据混淆。 `totalExpectedSignal` 是视场内期望信号,`totalDetectedSignalElectrons` 是视场内实际采样信号、尚未经过饱和丢失。`signalFractionInFOV` 表示捕获的整张 PSF 比例。`stats.mean/variance/min/max` 的单位分别为 ADU / ADU² / ADU / ADU;`centroidExpectedPx` 使用真值 PSF,`centroidMeasuredPx` 则对测量数据减背景后保留带符号的加权矩,无信号时可能不稳定。 `frame.snrEstimate` 使用整幅 ROI 的像元数,因此是全 ROI 积分 SNR;不要当作单离子的最佳口径 SNR。`aperturePhotometry` 返回每离子口径的实测电子数、局部背景、传播噪声、SNR、期望 SNR 和饱和标记。环形区使用算术平均,保留负背景和负净信号,避免截断负值带来的正偏置;噪声估计中的负背景会下限设为 0。使用环形背景时额外包含 `nPix²/nAnnulus` 的背景估计不确定度。邻近离子口径从背景环排除,但 PSF 尾部或未识别邻星仍可能污染背景,学生需比较口径及环半径。`snrExpected` 来自模型信号均值,应标记为预测值。饱和时 `valid=false`,因为裁切图像不再能做无偏测光。 `frameToCSV` 导出原始像元、物方坐标、ADU、折算输入电子及明确标注的仿真真值,附 seed、曝光、EM、转换增益及基线。显示拉伸不会进入导出数据。 `renderFrame` 支持固定 ADU 范围、百分位自动拉伸、gray/violet LUT 和饱和伪彩。自动拉伸可能使不同曝光下的图片看上去同样亮;应在画面明确标注 `minADU/maxADU`、自动/固定拉伸及 ADU 单位。它只改变显示映射,不编辑原始 ADU,不人为增加点像亮度。 ## 依据与边界 EM 随机增益和低照度测光依据 [Basden, Haniff & Mackay (2003), Photon counting strategies with low light level CCDs](https://arxiv.org/abs/astro-ph/0307305)。正确 arXiv 编号是 **astro-ph/0307305**。 EM 读噪折算及寄存器容量与动态范围的关系参考 [Andor:How To Calculate Dynamic Range in EMCCDs](https://andor.oxinst.com/learning/view/article/dynamic-range-emccds)。额外噪声因子约 √2 的说明参考 [Andor:EMCCD Technology in Spectroscopy](https://andor.oxinst.com/learning/view/article/emccd-technology-in-spectroscopy)。 尚未模拟逐级 CIC 位置分布、传输效率损失、固定图样噪声、热像元、宇宙线、像元串扰、溢出 blooming、EM 老化与增益漂移;高增益及可选有限增益 Gamma 模型不等价于完整电子级联。局部背景环和 Poisson 统计也不能代替实际相机暗场、平场、光子转移曲线及增益标定。 `node --test tests/camera.test.mjs` 包含 18 项验证,覆盖像元积分、视场裁切、随机重复性、低/高计数 Poisson 均值方差、EM 额外方差、读噪暗电流、三级饱和、标定与质心、无偏背景测光、SNR、ADC 量化预算及其 c/g 缩放、适配、DPR 与传感器显示比例,以及原始数据不随显示改变。