def __init__(self, n_beta): r"""New `CPsf` with Zernike polynomials up to radial order `n_beta`. The number of polynomials is `self.czern.nk`, i.e., :math:`N_\beta = (n_\beta + 1)(n_\beta + 2)/2`. """ self.czern = CZern(n_beta)
def test_normalisations_complex(self): log = logging.getLogger('TestZern.test_normalisations_complex') n_beta = 6 L, K = 400, 393 # polar grid pol = CZern(n_beta) fitBeta = FitZern(pol, L, K) t1 = time() pol.make_pol_grid(fitBeta.rho_j, fitBeta.theta_i) t2 = time() log.debug('make pol grid {:.6f}'.format(t2 - t1)) # cartesian grid cart = CZern(n_beta) dd = np.linspace(-1.0, 1.0, max(L, K)) xx, yy = np.meshgrid(dd, dd) t1 = time() cart.make_cart_grid(xx, yy) t2 = time() log.debug('make cart grid {:.6f}'.format(t2 - t1)) smap = np.isfinite(cart.eval_grid(np.zeros(cart.nk))) scale = (1.0 / np.sum(smap)) log.debug('') log.debug('{} modes, {} x {} grid'.format(n_beta, L, K)) for i in range(pol.nk): a = np.zeros(pol.nk) a[i] = 1.0 Phi_a = cart.eval_grid(a) for j in range(pol.nk): b = np.zeros(pol.nk) b[j] = 1.0 Phi_b = cart.eval_grid(b) ip = scale * np.sum(Phi_a[smap] * (Phi_b[smap].conj())) if i == j: eip = 1.0 else: eip = 0.0 iperr = abs(ip - eip) log.debug('<{:02},{:02}> = {:+e} {:+e}'.format( i + 1, j + 1, ip, iperr)) self.assertTrue(iperr < self.max_ip_err)
def __init__(self, unparsed): super().__init__() args = self.do_cmdline(unparsed) # plot objects phaseplot = PhasePlot(n=args.n_alpha) # to plot beta and the PSF betaplot = BetaPlot(args) # to plot the phase # complex-valued Zernike polynomials for the GPF ip = FitZern(CZern(args.n_beta), args.fit_L, args.fit_K) # real-valued Zernike polynomials for the phase phase_pol = RZern(args.n_alpha) phase_pol.make_pol_grid(ip.rho_j, ip.theta_i) # make a polar grid # real-valued Zernike coefficients alpha = np.zeros(phase_pol.nk) # set the alpha coefficients randomly if args.random: alpha1 = normal(size=alpha.size - 1) alpha1 = (args.rms / norm(alpha1)) * alpha1 alpha[1:] = alpha1 del alpha1 self.rms = args.rms self.alpha = alpha self.phase_pol = phase_pol self.ip = ip self.betaplot = betaplot self.phaseplot = phaseplot # fit beta coefficients from alpha coefficients self.alpha2beta() # make gui self.make_gui()
def test_fit_complex_numpy(self): log = logging.getLogger('TestFitZern.test_fit_complex_numpy') z = CZern(4) F = FitZern(z, self.L, self.K) theta_i = F.theta_i rho_j = F.rho_j c = normal(size=z.nk) + 1j * normal(size=z.nk) Phi = [z.eval_a(c, rh, th) for rh in rho_j for th in theta_i] time1 = time() ce = F._fit_slow(Phi) time2 = time() log.debug('elapsed FIT_LIST {:.6f}'.format(time2 - time1)) PhiN = np.array(Phi, order='F') time1 = time() ce2 = F.fit(PhiN) time2 = time() log.debug('elapsed FIT_NUMPY {:.6f}'.format(time2 - time1)) enorm = norm(ce2 - np.array(ce, order='F')) log.debug('enorm {:e}'.format(enorm)) self.assertTrue(enorm < self.max_enorm)
def test_fit_complex(self): log = logging.getLogger('TestFitZern.test_fit_complex') z = CZern(4) F = FitZern(z, self.L, self.K) theta_i = F.theta_i rho_j = F.rho_j c = normal(size=z.nk) + 1j * normal(size=z.nk) time1 = time() Phi = [z.eval_a(c, rh, th) for rh in rho_j for th in theta_i] time2 = time() log.debug('eval Phi {:.4f}'.format(time2 - time1)) time1 = time() ce = F._fit_slow(Phi) time2 = time() log.debug('elapsed time {:.4f}'.format(time2 - time1)) err1 = np.sqrt(sum([abs(c[i] - ce[i])**2 for i in range(z.nk)])) max1 = max([abs(c[i] - ce[i]) for i in range(z.nk)]) log.debug('err1 {:e} max1 {:e} max {:e}'.format( err1, max1, self.max_fit_norm)) self.assertTrue(err1 < self.max_fit_norm)
References ---------- .. [A2015] Jacopo Antonello and Michel Verhaegen, "Modal-based phase retrieval for adaptive optics," J. Opt. Soc. Am. A 32, 1160-1170 (2015) . `url <http://dx.doi.org/10.1364/JOSAA.32.001160>`__. """ if __name__ == '__main__': # grid sizes L, K = 95, 105 # complex-valued Zernike polynomials up to the 4-th radial order gpf_pol = CZern(4) # to approximate the GPF # FitZern computes the approximate inner products, see Eq. (B4) in [A2015] ip = FitZern(gpf_pol, L, K) gpf_pol.make_pol_grid(ip.rho_j, ip.theta_i) # make a polar grid # random vector of Zernike coefficients to be estimated beta_true = normal(size=gpf_pol.nk) + 1j * normal(size=gpf_pol.nk) # random generalised pupil function P P = gpf_pol.eval_grid(beta_true) # estimate the random vector from the GPF grid beta_hat = ip.fit(P) # plot the results
'--rms', type=float, default=1.0, help='Rms of the alpha aberration.') parser.add_argument( '--random', action='store_true', help='Make a random alpha aberration.') parser.add_argument( '--fit-L', type=int, default=95, metavar='L', help='Grid size for the inner products.') parser.add_argument( '--fit-K', type=int, default=105, metavar='K', help='Grid size for the inner products.') args = parser.parse_args() # complex-valued Zernike polynomials for the GPF ip = FitZern(CZern(args.n_beta), args.fit_L, args.fit_K) # real-valued Zernike polynomials for the phase phase_pol = RZern(args.n_alpha) phase_pol.make_pol_grid(ip.rho_j, ip.theta_i) # make a polar grid # real-valued Zernike coefficients alpha = np.zeros(phase_pol.nk) # nm to linear index conversion nmlist = list(zip(phase_pol.ntab, phase_pol.mtab)) # set an alpha coefficient using the (n, m) indeces if args.nm[0] != -1 and args.nm[0] != -1: try: k = nmlist.index(tuple(args.nm))