1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
| import numpy as np from typing import List import scipy.special as sp
class ZernikePolynomials: """Zernike多项式的实现"""
def __init__(self, order: int = 10): self.order = order
def zernike(self, n: int, m: int, rho: np.ndarray, theta: np.ndarray) -> np.ndarray: """计算Zernike多项式""" if (n - m) % 2 != 0: return np.zeros_like(rho)
R = np.zeros_like(rho) for s in range(0, (n - m) // 2 + 1): coeff = ((-1) ** s * sp.factorial(n - s) / (sp.factorial(s) * sp.factorial((n + m) // 2 - s) * sp.factorial((n - m) // 2 - s))) R += coeff * rho ** (n - 2 * s)
if m >= 0: angular = np.cos(m * theta) else: angular = np.sin(-m * theta)
return R * angular
def generate_wavefront(self, coefficients: List[float], size: int = 64) -> np.ndarray: """根据Zernike系数生成波前""" x = np.linspace(-1, 1, size) y = np.linspace(-1, 1, size) X, Y = np.meshgrid(x, y)
Rho = np.sqrt(X**2 + Y**2) Theta = np.arctan2(Y, X) mask = Rho <= 1
wavefront = np.zeros_like(Rho)
for j, coeff in enumerate(coefficients, start=1): if j <= len(coefficients): from self import noll_index_to_nm n, m = noll_index_to_nm(j) zernike_val = self.zernike(n, m, Rho, Theta) wavefront += coeff * zernike_val
return wavefront * mask
def noll_index_to_nm(self, j: int): """将Noll索引转换为(n, m)对""" n = int(np.ceil((np.sqrt(8 * j - 7) - 1) / 2)) m = ((2 * n + 1) * (n - 2) // 2 + j) % 2 * (n // 2) if j % 2 == 0 and m > 0: m = -m return n, abs(m)
def test_zernike_visualization(): """测试Zernike多项式的可视化"""
print("=" * 60) print("Zernike多项式可视化测试") print("=" * 60)
zernike = ZernikePolynomials(order=5)
test_cases = [ { "name": "Tip-Tilt (倾斜)", "coefficients": [0, 0.5, 0.3, 0, 0, 0] }, { "name": "Defocus (离焦)", "coefficients": [0, 0, 0, 1.0, 0, 0] }, { "name": "Astigmatism (像散)", "coefficients": [0, 0, 0, 0, 0.5, 0.3] } ]
for case in test_cases: print(f"\n{case['name']}") wavefront = zernike.generate_wavefront( case['coefficients'], size=64 ) print(f"波前统计: 均值={np.mean(wavefront):.4f}, 标准差={np.std(wavefront):.4f}") print(f"峰值: {np.max(wavefront):.4f}, 谷值: {np.min(wavefront):.4f}")
test_zernike_visualization()
|