This function either displays Zernike polynomials over a circular, hexagonal, elliptical, rectangular or annular shaped pupil, or fits surface data to these pupil shapes. See Mahajan, V.N., G.-m. Dai, "Orthonormal polynomials in wavefront analysis: analytical solution," J. Opt. Soc. Am. A, Vol. 24, No. 9, Sept. 2007 for a description of Zernike polynomials for non-circular pupil shapes. Can specify the Zernikes to use in j-ordering or (n,m) notation, Mahajan/Noll or Born&Wolf normalization, Fringe subset, and which sign convention to use. A mask can be specified to select a subset of the surface data to use to fit the Zernike polynomials. Least squares fit coefficients are calculated. If no surface data is specified then the function displays the sum of the Zernike polynomials specified over the pupil shape specified. The unit circle's center and radius in pixel units to be used in the fitting can be specified.
What format does the surface data have to be provided in? Is it a simple two dimensional array with "height" values?
Great work! Just one note. In calculateZernike function at line 824 the sign of m should be considered negative based on this reference : https://pdfs.semanticscholar.org/presentation/3a1d/7277d4654ff942cb1fcfc1257a7f3aa5c921.pdf
Considering this sign change, the Zernike coefficients will be consistent with Zemax Zernike coefficients calculation.
It takes a little bit to figure out how to get this script to do what you want, but once you figure out how to use it correctly this is a very powerful script! Just follow the excellent documentation and everything will run smoothly
Note that your data set cannot contain NaNs, otherwise the coeff output will be all NaNs
Thanks for putting all of this together -- this looks very comprehensive. One question though: for annular apertures, is the obscuration ratio computed in terms of distance or area? Thanks.
Within two hours, I'd read the help text, added a call to ZernikeCalc in my previously Amplitude-only OTF and PSF computation code, and verified I was getting accurate results from a defocus test case.
I spent an hour reviewing the help texts and basic approaches for the three or four major Zernike polynomial support functions in the community libraries and ZernikeCalc seemed the most straightforward and suited to my needs. It is simple to select a Zernike system, send it "J" coefficients and get zernike polynomials in return. A simple sum reduces them to the form I need. There's a lot more power in here that I don't need and yet the usage is simple for my simple needs.
My one request, after initial usage, would be a flag to have ZC to compute and return only a single summed matrix of the net ZC polynomials. And this is only to ease memory space needs for large computations.
First of all thanks for providing this great code, with excellent explanation. But I have a question considering the normalization of the Zernike polynomials. When using ZernikeDef ‘STANDARD’ it seems that their is no normalization. This came up after I wanted to retrieve some Zernike coefficients of a known surface. The surface data was made with normalized Zernike’s polynomials. But the output of you code was without the normalizations factors.
I fixed the issue by placing ‘result=theFactor.*result; ‘ before ‘switch ZernikeDef…..’. In the function result (row 789). Now my question is, whether this fix is correct and either of this is a problem in the first place?
Added non-circular default masks for non-circular pupil shapes to allow easy display of the non-circular polynomials.
Create scripts with code, output, and formatted text in a single executable document.