Skip to main content

Module zernike

Module zernike 

Source
Expand description

Zernike ordering conventions: normalization flags and the three single-index schemes.

The polynomials themselves are SpecialMath::zernike and zernike_r. What lives here is everything around them, which in practice is where the errors are.

A Zernike mode is named by two integers: the radial degree n >= 0 and the azimuthal frequency m, with |m| <= n and n - |m| even. Every application flattens that pair into a single running index, and there are three incompatible ways to do it, all in current use:

SchemeFirst indexOrdering within a degreeFound in
ANSI Z80.28 / OSA0m ascending from -n to +nophthalmology, most Python tooling
Noll1|m| ascending, sign alternating by n mod 4astronomy, Zemax “Standard” coefficients
Fringe (Air Force / Arizona)1by spatial frequency n + |m|, cosine before sineinterferometry, Zemax “Fringe” coefficients

Handing a Noll-indexed coefficient vector to ANSI-indexed code produces a plausible-looking wavefront that is wrong from the second term on, and nothing in the numbers announces it. Converting explicitly at the boundary is the fix, which is why these are here rather than left to the caller.

Normalization is the second, independent axis. ZERNIKE_UNIT_PEAK leaves the radial polynomial alone, so every mode has R_n^m(1) = 1 and coefficients read as peak wavefront amplitude. ZERNIKE_ORTHONORMAL applies $N_n^m = \sqrt{2(n+1)/(1 + \delta_{m,0})}$, making the modes orthonormal on the unit disc under the $1/\pi$-weighted inner product, so a coefficient is an RMS contribution and the total wavefront RMS is the root-sum-square of them. Both the ANSI and Noll standards specify the orthonormal form, while unit-peak is what most hand-rolled shader and interferometer code produces. There is no safe default, so the choice is a required const generic rather than a flag with an opinion.

All conversions here are const fn over plain integers. They are configuration, evaluated once per mode and not per sample, and never belong in a vector loop.

Constants§

ZERNIKE_ORTHONORMAL
Scale each mode by $\sqrt{2(n+1)/(1 + \delta_{m,0})}$, the ANSI Z80.28 and Noll normalization.
ZERNIKE_UNIT_PEAK
Leave the radial polynomial unnormalized: $R_n^m(1) = 1$ for every mode.

Functions§

ansi_index
The ANSI Z80.28 / OSA single index of mode (n, m): $j = (n(n+2) + m)/2$, from 0.
ansi_to_nm
The mode (n, m) carrying ANSI index j. Inverse of ansi_index.
count_up_to_degree
The number of Zernike modes with radial degree at most n, i.e. (n+1)(n+2)/2.
fringe_index
The Fringe (Air Force / Arizona) single index of mode (n, m), from 1.
fringe_to_ansi
The ANSI index of the mode carrying Fringe index j.
fringe_to_nm
The mode (n, m) carrying Fringe index j. Inverse of fringe_index.
is_valid
Whether (n, m) names a real Zernike mode: $|m| \le n$ with $n - |m|$ even.
noll_index
The Noll single index of mode (n, m), from 1.
noll_to_ansi
The ANSI index of the mode carrying Noll index j.
noll_to_nm
The mode (n, m) carrying Noll index j. Inverse of noll_index.
Last built: 2026-09-08 21:35:55 UTC