forked from handofkwll/fisica
-
Notifications
You must be signed in to change notification settings - Fork 0
/
zernike.py
45 lines (39 loc) · 1.61 KB
/
zernike.py
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
# Zernike routines written by Tim van Werkhoven (werkhoven@strw.leidenuniv.nl)
# Subset of his module libtim-py, code reformatted.
import numpy as np
from scipy.misc import factorial as fac
def zernike_rad(m, n, rho):
"""
Make radial Zernike polynomial on coordinate grid **rho**.
@param [in] m Radial Zernike index
@param [in] n Azimuthal Zernike index
@param [in] rho Radial coordinate grid
@return Radial polynomial with identical shape as **rho**
"""
if (np.mod(n-m, 2) == 1):
return rho*0.0
wf = rho*0.0
for k in range((n-m)/2+1):
wf += rho**(n-2.0*k) * (-1.0)**k * fac(n-k) / \
( fac(k) * fac( (n+m)/2.0 - k ) * fac( (n-m)/2.0 - k ) )
return wf
def zernike(m, n, rho, phi, norm=True):
"""
Calculate Zernike mode (m,n) on grid **rho** and **phi**.
**rho** and **phi** should be radial and azimuthal coordinate grids of identical shape, respectively.
@param [in] m Radial Zernike index
@param [in] n Azimuthal Zernike index
@param [in] rho Radial coordinate grid
@param [in] phi Azimuthal coordinate grid
@param [in] norm Normalize modes to unit variance
@return Zernike mode (m,n) with identical shape as rho, phi
@see <http://research.opt.indiana.edu/Library/VSIA/VSIA-2000_taskforce/TOPS4_2.html> and <http://research.opt.indiana.edu/Library/HVO/Handbook.html>.
"""
nc = 1.0
if (norm):
nc = (2*(n+1)/(1+(m==0)))**0.5
if (m > 0):
return nc*zernike_rad(m, n, rho) * np.cos(m * phi)
if (m < 0):
return nc*zernike_rad(-m, n, rho) * np.sin(-m * phi)
return nc*zernike_rad(0, n, rho)