"""Math functions for computing Zernike polynomial information. 
TODO: write tests and document these functions properly
"""
import numpy as np
[docs]def Rnm_p(n,m):
    """ Generate radial polynomial for radial Zernikee"""
    pc = []
    m = abs(m)
    for ik in range(int((n-m)/2)+1):
        num = (-1)**ik *np.math.factorial(int(n-ik))
        den = np.math.factorial(int(ik))*np.math.factorial(int((n+m)/2-ik))*np.math.factorial(int((n-m)/2-ik))
        pc.append(num/den)
    return np.array(pc) 
[docs]def Rnm_eval(_r, _phi, n, m, a0):
    """Function to evaluate  radial components"""
    # Obtain the polynomial coeffs:
    pn = Rnm_p(n,m)
    Rnm = np.zeros(_r.shape)
    for idx, ip in enumerate(pn):
        Rnm +=  ip*(_r/a0)**(n-2*idx)
    # Noll normalissation:
    Nnm = np.sqrt(2*n+2)
    return Nnm*Rnm 
[docs]def ZPhi_eval(_phi, m):
    """ Fuction to generate azimuthal component """
    if m < 0:
        ZPhi = 1/np.sqrt(np.pi)*np.sin(m*_phi)
    elif m>0:
        ZPhi =  1/np.sqrt(np.pi)*np.cos(m*_phi)
    else:
        ZPhi = 1/np.sqrt(2*np.pi)*np.ones(_phi.shape)
    return ZPhi 
[docs]def Znm_eval(_r,_phi, n, m, a0):
    _Rnm = Rnm_eval(_r, _phi, n, m, a0)
    _Pnm = ZPhi_eval(_phi, m)
    return  _Rnm*_Pnm 
[docs]def Gen_nm(n):
    """Generate n and m  vectors containing n and m indices up to n, excluding zeroth mode"""
    vlen = np.sum(np.arange(2,n+2))
    _n = np.zeros(vlen)
    _m = np.zeros(vlen)
    for iN in range(1,n+1):
        iStart=(np.sum(np.arange(2,iN-1+2)))
        iStop=(np.sum(np.arange(2,iN+2)))
        _n[iStart:iStop] = iN
        for im in range(iN+1):
            _m[iStart+im] = -iN+im*2
    return _n,_m