这道题gemini 2.5 pro做出来了,虽然不是一次做对的。 https://ai.studio/apps/drive/1D6FZW1zzal_TnGvfNqbh9oDdyX93eStF

开发规划文档

项目: Zernike 像差到光学质量 (PSF/OTF) 计算器
版本: 0.1 (MVP)
文档日期: 2025年10月28日

1.0 项目概述

1.1 项目背景

在眼科光学和视觉科学领域,人眼像差通常使用Zernike多项式系数来量化。像差仪、角膜地形图和波前引导手术设备(如屈光手术)都会生成这些系数。然而,Zernike系数本身(例如“0.5μm0.5 \mu\text{m} 的彗差 C31C_3^1”)对于临床医生、研究人员甚至患者来说都非常抽象。它们无法直观地回答一个关键问题:“这种像差到底对视觉质量有多大影响?”

本项目旨在开发一个计算工具,弥合这一差距。它将抽象的Zernike系数转换为视觉科学中最基本、最直观的光学质量指标:

  • 点扩散函数 (PSF): 一个理想的点光源(如远处的一颗星星)在视网膜上实际形成的模糊图像。
  • 光学传递函数 (OTF): 描述光学系统(人眼)传递不同空间频率对比度的能力。OTF 包含:
    • 调制传递函数 (MTF): 对比度衰减的幅度(“图像有多模糊”)。
    • 相位传递函数 (PTF): 相位是如何移动的(“图像形态扭曲了多少”,例如鬼影)。

通过本工具,用户可以直观地“看到”不同像差组合对成像质量的实际影响。

1.2 项目目标 (MVP)

开发一个核心计算引擎(MVP),该引擎接收符合特定行业标准(ANSI Z80.28)的Zernike系数,并计算出人眼模型的单色点扩散函数(PSF)、光学传递函数(OTF)、调制传递函数(MTF)和相位传递函数(PTF)。

1.3 核心假设与限制 (MVP v0.1)

此MVP版本仅支持一种固定的数据标准。用户(或调用者)有责任确保其输入数据符合以下规范。任何不符合这些规范的输入都将导致错误的计算结果。

  • Zernike 标准: ANSI Z80.28 / ISO 24157 (使用 ZnmZ_n^m 双索引)。
  • 归一化 (Normalization): 正交归一化 (Orthonormal)。
  • 系数单位 (Units): 微米 (μm\mu\text{m})。
  • 光学模型: 单色光(Monochromatic)计算。
  • 瞳孔模型: 均匀透射的圆形光阑(不考虑Stiles-Crawford效应)。

2.0 理论基础与计算公式

本程序是基于傅里叶光学(Fourier Optics)的标准模型实现的。

2.1 Zernike 波前重建

波前像差 WW 是在瞳孔平面上定义的。它通过Zernike系数 CnmC_n^m 和对应的Zernike多项式 ZnmZ_n^m 线性叠加而成。

W(ρ,θ)=n,mCnmZnm(ρ,θ) W(\rho, \theta) = \sum_{n, m} C_n^m \cdot Z_n^m(\rho, \theta)

  • W(ρ,θ)W(\rho, \theta) 是在瞳孔平面上的波前像差(单位:μm\mu\text{m})。
  • (ρ,θ)(\rho, \theta) 是归一化的极坐标(ρ\rho 从 0 到 1)。
  • CnmC_n^m 是输入的Zernike系数(单位:μm\mu\text{m}),对应 (n, m) 阶。
  • ZnmZ_n^m 是 ANSI Z80.28 标准定义的Zernike多项式(无单位)。

2.2 瞳函数 (Pupil Function)

瞳函数 P(x,y)P(x, y) 是一个复数函数,它完整地描述了光线如何通过瞳孔。

P(x,y)=A(x,y)eiϕ(x,y) P(x, y) = A(x, y) \cdot e^{i \cdot \phi(x, y)}

  • 振幅 A(x,y)A(x, y): 定义了瞳孔的形状和透光率。在MVP中,这是一个二元圆形掩模:

    A(x,y)={1if x2+y2Rpupil0otherwise A(x, y) = \begin{cases} 1 & \text{if } \sqrt{x^2+y^2} \le R_{\text{pupil}} \\ 0 & \text{otherwise} \end{cases}

  • 相位 ϕ(x,y)\phi(x, y): 描述了波前的畸变。

    ϕ(x,y)=2πλW(x,y) \phi(x, y) = \frac{2\pi}{\lambda} \cdot W(x, y)

2.3 傅里叶光学 (PSF & OTF)

根据夫琅禾费衍射理论,PSF 和 OTF 可以通过傅里叶变换计算得出:

PSF (点扩散函数):
PSF 是瞳函数 P(x,y)P(x, y) 的傅里叶变换的模的平方。

PSF=F{P(x,y)}2 \text{PSF} = |\mathcal{F}\{P(x, y)\}|^2

OTF (光学传递函数):
根据维纳-辛钦定理 (Wiener–Khinchin theorem),OTF 是 PSF 的傅里叶变换。

OTF=F{PSF} \text{OTF} = \mathcal{F}\{\text{PSF}\}

2.4 关键性能指标 (Metrics)

MTF (调制传递函数): OTF 的模。

MTF(fx,fy)=OTFnorm(fx,fy) \text{MTF}(f_x, f_y) = |\text{OTF}_{\text{norm}}(f_x, f_y)|

PTF (相位传递函数): OTF 的相位角。

PTF(fx,fy)=angle(OTFnorm(fx,fy)) \text{PTF}(f_x, f_y) = \text{angle}(\text{OTF}_{\text{norm}}(f_x, f_y))

Strehl Ratio (斯特列尔比):
有像差系统的PSF峰值 PSFaberrated\text{PSF}_{\text{aberrated}} 与同一系统在衍射极限下(无像差)的PSF峰值 PSFideal\text{PSF}_{\text{ideal}} 之比。

Strehl Ratio=PSFaberrated(peak)PSFideal(peak) \text{Strehl Ratio} = \frac{\text{PSF}_{\text{aberrated}}(\text{peak})}{\text{PSF}_{\text{ideal}}(\text{peak})}

2.5 核心单位转换

空间频率 (lp/mm \leftrightarrow cpd):
feyef_{\text{eye}}: 用户输入的眼球焦距 (mm) (例如 16.67 mm)。
flp/mmf_{\text{lp/mm}}: 视网膜上的空间频率 (线对/毫米)。
fcpdf_{\text{cpd}}: 视角空间频率 (周/度)。

转换公式:

fcpd=flp/mmfeyetan(1) f_{\text{cpd}} = f_{\text{lp/mm}} \cdot f_{\text{eye}} \cdot \tan(1^\circ)

空间坐标 (mm \leftrightarrow arcmin):
xx: 视网膜上的距离 (mm)。
αarcmin\alpha_{\text{arcmin}}: 对应的视角 (角分)。

转换公式:

αrad=arctan(xfeye)xfeye \alpha_{\text{rad}} = \arctan\left(\frac{x}{f_{\text{eye}}}\right) \approx \frac{x}{f_{\text{eye}}}

3.0 用户需求文档 (URD) v0.1

3.1 📋 功能需求 (Functional Requirements)

FR-1: 用户输入(计算参数)

用户必须能够为每次计算提供以下参数:

FR-1.1: Zernike 系数列表
  • 描述: 程序的输入核心。用户需提供一组Zernike系数。
  • 格式: 应为 (n, m, C) 的组合,其中 nn 为径向阶数,mm 为方位角频率,CC 是以 μm\mu\text{m} 为单位的系数值。
FR-1.2: 瞳孔直径 (Pupil Diameter)
  • 描述: Zernike系数所对应的瞳孔大小。
  • 单位: mm\text{mm}
FR-1.3: 计算波长 (Wavelength)
  • 描述: 用于计算的单色光波长。
  • 单位: nm\text{nm} (例如: 550 nm)。
FR-1.4: 眼球焦距 (Focal Length)
  • 描述: 用于空间频率单位转换的简化眼模型焦距(后节点到像面的距离)。
  • 单位: mm\text{mm}
  • 备注: 程序应提供一个合理的默认值(例如 16.67 mm16.67 \text{ mm},对应约 60D 的眼球屈光力),但必须允许用户覆盖此值。

FR-2: 核心计算(后端引擎)

系统必须在内部执行以下计算:

  • FR-2.1: 波前重建 (Wavefront Map): 根据输入的Zernike系数 (FR-1.1) 和瞳孔直径 (FR-1.2),在一个N x N的网格上重建出2D的波前像差图 W(x,y)W(x, y),单位为 μm\mu\text{m}
  • FR-2.2: 瞳函数 (Pupil Function) 生成: 构建复数瞳函数 P(x,y)=A(x,y)eiϕ(x,y)P(x, y) = A(x, y) \cdot e^{i \cdot \phi(x, y)}
    • 振幅 A(x,y)A(x, y): 在 (FR-1.2) 定义的瞳孔直径内为 1,直径外为 0。
    • 相位 ϕ(x,y)\phi(x, y): ϕ=2πλW(x,y)\phi = \frac{2\pi}{\lambda} \cdot W(x, y),其中 W(x,y)W(x, y) 来自 (FR-2.1),λ\lambda 来自 (FR-1.3)。
  • FR-2.3: PSF 计算: 计算2D的点扩散函数 (PSF)。
    • 方法: PSF=F{P(x,y)}2PSF = |\mathcal{F}\{P(x, y)\}|^2F\mathcal{F} 是2D傅里叶变换,应使用FFT实现)。
  • FR-2.4: OTF 计算: 计算2D的光学传递函数 (OTF)。
    • 方法: OTF=F{PSF}OTF = \mathcal{F}\{PSF\} (根据维纳-辛钦定理)。
    • 归一化: OTF必须被归一化,使其在零频率 OTF(0,0)OTF(0, 0) 处的值为 1。
  • FR-2.5: 衍射极限 (Diffraction-Limited) 参考计算: 系统必须使用相同的参数(FR-1.2, FR-1.3, FR-1.4),但将所有Zernike系数设为0,计算出理想的、无像差的 PSFidealPSF_{\text{ideal}},用于 (FR-3.5) 的计算。

FR-3: 数据输出(计算结果)

系统必须向用户提供以下有意义的结果:

  • FR-3.1: 2D PSF 图像/数据:
    • 显示: 应能以线性标尺和对数标尺 (Log Scale) 两种方式显示,以便观察光晕和衍射环。
    • 坐标轴: 空间坐标轴应能映射为 视角 (arcmin 或 degree) 或 视网膜上的 μm\mu\text{m}
  • FR-3.2: 2D MTF 图像/数据:
    • 描述: 显示2D MTF的“俯视图”,直观展示不同方向的调制传递特性。
  • FR-3.3: 1D MTF 曲线:
    • 描述: 提供 径向平均 (Radially Averaged) 后的1D MTF曲线图。
    • Y轴: 调制深度 (Modulation),范围 0 到 1。
    • X轴 (空间频率): 必须提供单位换算选项:cycles/degree (cpd),lp/mm。
  • FR-3.4: 1D PTF 曲线:
    • 描述: 提供 特定方向切片 (Slice) 的1D相位传递函数曲线(注: PTF不应进行径向平均)。
    • Y轴: 相位 (Phase),单位为 弧度 (Radians) 或 角度 (Degrees)。
    • X轴 (空间频率): 必须与 (FR-3.3) 的X轴(cpd, lp/mm)保持一致,以便对比。
  • FR-3.5: 斯特列尔比 (Strehl Ratio):
    • 描述: 提供一个单一数值,作为光学质量的快速摘要。
    • 计算: StrehlRatio=PSFaberrated(peak)PSFideal(peak)Strehl \, Ratio = \frac{\text{PSF}_{\text{aberrated}}(\text{peak})}{\text{PSF}_{\text{ideal}}(\text{peak})},其中 PSFidealPSF_{\text{ideal}} 来自 (FR-2.5)。

3.2 📚 非功能需求 (Non-Functional Requirements)

  • NFR-1: 文档 (README.md 或 "关于" 页面):
    • NFR-1.1 (标准声明): 必须在文档的显著位置清晰声明:本程序MVP版本仅接受 ANSI Z80.28 (双索引 ZnmZ_n^m)、正交归一化、单位为 μm\mu\text{m} 的Zernike系数。
    • NFR-1.2 (警告): 必须包含一个“警告”部分,说明:如果输入了其他标准(如Noll单索引、Fringe索引、P-V归一化或'waves'单位)的数据,将导致计算结果完全错误。
  • NFR-2: 性能: 对于常规计算(例如10阶Zernike系数,256x256计算网格),PSF/OTF的完整计算应在数秒内完成。
  • NFR-3: 精度: 在执行 (FR-2.3) 的FFT之前,必须对 (FR-2.2) 的瞳函数矩阵进行充分的补零 (Zero Padding)(例如,将 256x256 补到 1024x1024 或更高),以保证PSF的采样精度并避免OTF的混叠。

4.0 🏛️ 公理设计分析 (Axiomatic Design)

公理设计的核心是将“做什么”(功能需求 FR)映射到“怎么做”(设计参数 DP),并尽量保持这种映射关系的独立性。

4.1 映射表 (FR → DP)

功能需求 (FR) 描述 (做什么) 设计参数 (DP) 实现 (怎么做)
FR-1: 用户输入 接收所有计算参数 DP-1: ParameterConfig 对象 一个数据类 (dataclass)、结构体 (struct) 或纯粹的对象 (plain object),用于封装所有输入 (FR-1.1 至 1.4)。
FR-1.1 Zernike 系数列表 DP-1.1: Zernike (n, m, C) 列表 一个数组的数组 (Array of Arrays)、元组列表 (List of Tuples) 或键值映射 (Map/Dictionary)。
FR-1.2 瞳孔直径 DP-1.2: pupil_diameter_mm 变量 一个浮点数 (Float) 类型的变量。
FR-1.3 计算波长 DP-1.3: wavelength_nm 变量 一个浮点数类型的变量。
FR-1.4 眼球焦距 DP-1.4: focal_length_mm 变量 一个浮点数类型的变量,具有 16.67 mm16.67 \text{ mm} 的默认值。
FR-2: 核心计算 执行光学变换 DP-2: OpticalEngine 模块 一个核心计算模块,包含执行傅里叶光学的函数。
FR-2.1 波前重建 DP-2.1: reconstruct_wavefront 函数 一个函数,输入 DP-1.1 和网格大小,循环Zernike多项式并求和,输出 2D 波前图 W(x,y)W(x, y)
FR-2.2 瞳函数生成 DP-2.2: create_pupil_function 函数 一个函数,输入 W(x,y)W(x, y) 和 DP-1.3,计算 eiϕe^{i \phi};并应用一个圆形二元掩模 (Mask) 和补零 (NFR-3)。
FR-2.3 PSF 计算 DP-2.3: calculate_psf 函数 一个函数,对 DP-2.2 的输出执行 2D FFT、FFT 移位和取模的平方。
FR-2.4 OTF 计算 DP-2.4: calculate_otf 函数 一个函数,对 DP-2.3 的输出执行 2D FFT、FFT 移位,并归一化。
FR-2.5 衍射极限参考 DP-2.5: 对 DP-2 的复用 一个流程,使用空的 Zernike 系数列表 (DP-1.1) 调用 DP-2.1 至 DP-2.3,以生成 PSFidealPSF_{\text{ideal}}
FR-3: 数据输出 分析和格式化结果 DP-3: Analysis 模块 一个后处理模块,用于从原始 PSF/OTF 数据中提取可用的指标。
FR-3.1 2D PSF (对数) DP-3.1: process_psf_2d 函数 一个函数,对 PSFPSF 数据取 log10log_{10} 并处理 log(0)log(0) 的情况。
FR-3.2 2D MTF DP-3.2: get_mtf_2d 函数 一个函数,对 OTFOTF 数据取 abs() (复数取模)。
FR-3.3 1D MTF (径向平均) DP-3.3: calculate_radial_mtf 函数 -
FR-3.4 1D PTF (切片) DP-3.4: get_ptf_slice 函数 一个函数,对 OTFOTF 数据取 angle() (复数取相位角),并提取指定方向的切片。
FR-3.5 Strehl Ratio DP-3.5: calculate_strehl 函数 一个函数,输入 PSFaberratedPSF_{\text{aberrated}}PSFidealPSF_{\text{ideal}},返回二者峰值之比。
FR (隐式) 为图表生成正确的坐标轴 DP-4: UnitConverter 模块 一个工具模块,用于处理物理单位和坐标轴的映射。
(来自FR-3.1) PSF 坐标 (arcmin/µm) DP-4.1: generate_spatial_axes 函数 一个函数,根据焦距 (DP-1.4) 和阵列大小,计算像平面的空间坐标。
(来自FR-3.3/4) OTF 坐标 (cpd/lp/mm) DP-4.2: generate_frequency_axes 函数 一个函数,根据焦距 (DP-1.4) 和阵列大小,计算频率平面的坐标。

4.2 设计评估

此设计是高度解耦 (Decoupled) 的。
DP-1 (输入) → DP-2 (计算) → DP-3 (分析) → DP-4 (单位)。

我们可以独立更改 DP-2 中的 FFT 算法(例如,切换库),而不会破坏 DP-3 的 Strehl Ratio 计算。我们可以独立更改 DP-4 中的 cpd 计算公式(例如,从 tan(1°) 改为小角度近似),而不会破坏 DP-2 的 OTF 计算。

这种设计是健壮且易于维护的,符合公理设计的独立性公理。

5.0 🧩 模块化设计 (技术栈无关)

基于上述 DP,我们定义以下逻辑模块。这些模块可以实现为命名空间 (Namespaces)、独立的类 (Classes) 或文件 (Modules)。

Main Controller (应用主入口)

  • 职责: 作为程序的入口点和协调器。
  • 功能:
    • 接收用户输入(在MVP中可能只是硬编码的配置对象)。
    • 创建 ParameterConfig 数据结构 (DP-1)。
    • 按顺序调用 Zernike Engine、Optics Engine 和 Analysis Engine。
    • 调用 Visualization 模块来显示结果。

Zernike Engine (Zernike 核心)

  • 职责: 所有与Zernike多项式相关的数学计算。
  • 关键依赖: 一个数学库(用于处理三角函数 sin, cos 和阶乘)。
  • 接口 (Interface) / 导出的函数:
    • zernike_ansi(n, m, rho, theta): (DP-2.1) 计算单个 ANSI 标准 Zernike 多项式在 (ρ,θ)(\rho, \theta) 坐标的值。
    • reconstruct_wavefront(coeffs, ...): (DP-2.1) 循环调用 zernike_ansi,构建 2D 波前图 W(x,y)W(x, y)

Optics Engine (傅里叶光学引擎)

  • 职责: 执行核心的物理光学计算。
  • 关键依赖: 一个支持复数 (Complex Numbers) 运算和 2D 快速傅里叶变换 (FFT) 的数值计算库。
  • 接口 (Interface) / 导出的函数:
    • create_pupil_function(wavefront_map, ...): (DP-2.2) 创建带补零的复数瞳函数矩阵。
    • calculate_psf(pupil_function): (DP-2.3) 计算 PSF。
    • calculate_otf(psf): (DP-2.4) 计算 OTF。

Analysis Engine (后处理与分析)

  • 职责: 从原始的 2D 矩阵数据中提取有意义的度量。
  • 关键依赖: 一个数值计算库(用于矩阵操作、取模、取相位、求和、查找峰值)。
  • 接口 (Interface) / 导出的函数:
    • process_psf_2d(psf_data): (DP-3.1) 生成对数标尺 PSF。
    • get_mtf_2d(otf_data): (DP-3.2) 提取 2D MTF。
    • calculate_radial_mtf(mtf_2d): (DP-3.3) 实现径向平均。
    • get_ptf_slice(otf_data, axis): (DP-3.4) 提取 PTF 切片。
    • calculate_strehl(psf_aber, psf_ideal): (DP-3.5) 计算 Strehl 比。

Utilities (实用工具与单位转换)

  • 职责: 提供坐标轴生成和单位转换。
  • 关键依赖: 基础数学库。
  • 接口 (Interface) / 导出的函数:
    • generate_spatial_axes(config): (DP-4.1) 计算 μm\mu\text{m}arcmin\text{arcmin} 坐标。
    • generate_frequency_axes(config): (DP-4.2) 计算 lp/mm\text{lp/mm}cpd\text{cpd} 坐标。

Visualization (结果可视化)

  • 职责: 将分析后的数据绘制成图表。
  • 关键依赖: 一个 2D 绘图/图表库。
  • 接口 (Interface) / 导出的函数:
    • plot_psf(psf_data_linear, psf_data_log, axes): 绘制 2D PSF 图像 (热力图或等高线图)。
    • plot_mtf_ptf(mtf_1d, ptf_1d, freq_axes, mtf_ideal_1d): 绘制 1D MTF/PTF 曲线 (折线图)。

6.0 🚀 项目实施计划 (技术栈无关)

这是一个按技术依赖排序的实施步骤(不含时间估计)。

阶段 0: 项目设置

  1. 初始化版本控制系统 (Git)。
  2. 初始化项目环境 (例如 npm, pip, conda 等)。
  3. 确定并安装核心依赖库:
    • 数值计算与 FFT 库
    • 2D 绘图库

阶段 1: Zernike 核心 (Zernike Engine)

  1. 实现 zernike_ansi 函数 (DP-2.1)。
  2. 单元测试 1.1: 使用已知的 (n,m)(n, m) 值(如 Z20Z_2^0 离焦)验证其数学形态是否正确。
  3. 实现 reconstruct_wavefront 函数 (DP-2.1)。
  4. 单元测试 1.3: 传入一个纯离焦系数,验证生成的波前图是否为正确的抛物面。

阶段 2: 傅里叶光学引擎 (Optics Engine)

  1. 实现 create_pupil_function (DP-2.2),包括圆形掩模和补零 (NFR-3)。
  2. 实现 calculate_psf (DP-2.3)。
  3. 实现 calculate_otf (DP-2.4)。
  4. 关键集成测试 (衍射极限):
    1. 设置 Zernike 系数为 0 (DP-2.5)。
    2. 运行 2.1 → 2.2 → 2.3 计算。
    3. 验证:
      • PSFidealPSF_{\text{ideal}} 是否为艾里斑 (Airy Disk)。
      • MTFidealMTF_{\text{ideal}} (即 OTF 的模) 是否为已知的圆形成孔径的 MTF 理论曲线。(此步骤是 MVP 成功的关键验证点)

阶段 3: 分析与坐标 (Analysis Engine & Utilities)

  1. 实现 calculate_strehl (DP-3.5)。(需要 2.4 的 PSFidealPSF_{\text{ideal}} 峰值)。
  2. 实现 calculate_radial_mtf (DP-3.3)。
  3. 实现 get_ptf_slice (DP-3.4)。
  4. 实现 generate_spatial_axes (DP-4.1) 和 generate_frequency_axes (DP-4.2)。
  5. 单元测试 3.4: 验证焦距 16.67mm16.67\text{mm} (60D) 下, 1 cpd1 \text{ cpd} 是否正确对应于 1/(16.67tan(1))3.44 lp/mm1 / (16.67 \cdot \tan(1^\circ)) \approx 3.44 \text{ lp/mm}

阶段 4: 编排与可视化 (Main Controller & Visualization)

  1. 创建 Main Controller (DP-1),硬编码一组测试参数(如 0.5μm0.5 \mu\text{m}Z20Z_2^0 离焦)。
  2. 在 Main Controller 中按顺序调用 core 模块,完成从输入到分析的全流程。
  3. 创建 plot_psf 函数 (DP-3.1),并显示结果(包括对数标尺)。
  4. 创建 plot_mtf_ptf 函数 (DP-3.3, 3.4),并显示结果。

阶段 5: 最终验证与文档

  1. 集成测试 (像差):
    1. 使用已知的像差(如纯离焦、纯散光、纯彗差)运行全流程。
    2. 验证:
      • 离焦是否导致 PSF 弥散,Strehl 下降,MTF 在中频衰减。
      • 散光是否导致 PSF 呈椭圆或线状,MTF 在两个正交方向上不一致。
      • 彗差是否导致 PSF 出现拖尾,并且 PTF 曲线出现显著的非零相位。
  2. 创建 README.md 文件(或同等的项目文档)。
  3. 重要 在文档中添加 URD 中的 NFR-1.1 (标准声明) 和 NFR-1.2 (警告)。