def V(self, n, m, r, f, L_max=35, ncpus=-1): r"""Evaluate :math:`V_n^m(r, f)`. Compute .. math:: V_n^m(r, f) = \epsilon_m \exp(if) \sum_{l=1}^{L_max}(-2if)^{l - 1} \sum_{j=0}^{(n - |m|)/2} v_{l,j} (1/l(2\pi r)^l)J_{|m| + l + 2j}(2\pi r). See Eq. (2.48) in [B2008]_. Parameters ---------- - `n`: `numpy` vector of integers for the radial orders `n` - `m`: `numpy` vector of integers for the azimuthal frequencies `m` - `r`: `numpy` vector of doubles for the radial coordinate :math:`r`, which is normalised to the diffraction unit `wavelength/NA` - `f`: `numpy` vector of complex numbers for the defocus parameter, see [J2002]_, [B2008]_, and [H2010]_ - `L_max`: optional `int` for the truncation order of the series, see [J2002]_, [B2008]_, and [H2010]_. `L_max <= 0` uses the default value of `35`. - `ncpus` : optional `int` for the number of threads. `-1` chooses all available cpus Returns ------- - `vnm`: `numpy` array of shape `(r.size, f.size, n.size)` for :math:`V_n^m(r, f)` References ---------- .. [J2002] A. J. E. M. Janssen, "Extended Nijboer–Zernike approach for the computation of optical point-spread functions," J. Opt. Soc. Am. A 19, 849–857 (2002). `doi <http://dx.doi.org/10.1364/JOSAA.19.000849>`__. .. [B2008] J. Braat, S. van Haver, A. Janssen, P. Dirksen, Chapter 6 Assessment of optical systems by means of point-spread functions, In: E. Wolf, Editor(s), Progress in Optics, Elsevier, 2008, Volume 51, Pages 349-468, ISSN 0079-6638, ISBN 9780444532114. `doi <http://dx.doi.org/10.1016/S0079-6638(07)51006-1>`__. .. [H2010] S. van Haver, The Extended Nijboer-Zernike Diffraction Theory and its Applications (Ph.D. thesis, Delft University of Technology, The Netherlands, 2010). `doi <http://resolver.tudelft.nl/uuid:8d96ba75-24da-4e31-a750-1bc348155061>`__. """ n = self._numpify(n, np.int) m = self._numpify(m, np.int) r = self._numpify(r, np.float) f = self._numpify(f, np.complex) Vnm = vnmpocnp(r, f, n, m, L_max=L_max, ncpus=ncpus) if Vnm.size == 1: return complex(Vnm[0, 0, 0]) else: return Vnm
def U(self, beta, r, phi, f): r"""Evaluate the complex point spread function at a point. The complex point-spread function is .. math:: U(r, \phi, f) = 2 \sum_{n, m} \beta_{n}^{m} \sqrt{n + 1} i^{m} V_n^m(r, f) \exp(im\phi). See Eq. (4) in [A2015]_. Parameters ---------- - `beta`: `list` of the complex Zernike coefficients :math:`\beta_n^m` - `r`: float for the radial coordinate :math:`r`, normalised to the diffraction unit `wavelength/NA` - `phi`: float for the azimuthal coordinate :math:`\phi` - `f`: complex-valued defocus parameter, see [J2002]_, [B2008]_, and [H2010]_ Returns ------- - `U`: complex value of :math:`U(r, \phi, f)` 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>`__. .. [J2002] A. J. E. M. Janssen, "Extended Nijboer–Zernike approach for the computation of optical point-spread functions," J. Opt. Soc. Am. A 19, 849–857 (2002). `doi <http://dx.doi.org/10.1364/JOSAA.19.000849>`__. .. [B2008] J. Braat, S. van Haver, A. Janssen, P. Dirksen, Chapter 6 Assessment of optical systems by means of point-spread functions, In: E. Wolf, Editor(s), Progress in Optics, Elsevier, 2008, Volume 51, Pages 349-468, ISSN 0079-6638, ISBN 9780444532114. `doi <http://dx.doi.org/10.1016/S0079-6638(07)51006-1>`__. .. [H2010] S. van Haver, The Extended Nijboer-Zernike Diffraction Theory and its Applications (Ph.D. thesis, Delft University of Technology, The Netherlands, 2010). `doi <http://resolver.tudelft.nl/uuid:8d96ba75-24da-4e31-a750-1bc348155061>`__. """ U = complex(0.0) r = self._numpify(r, np.float) f = self._numpify(f, np.complex) assert (r.size == 1) assert (f.size == 1) n, m = np.array([0]), np.array([0]) for i in range(self.czern.nk): n[0], m[0] = self.czern.ntab[i], self.czern.mtab[i] cf = self.czern.coefnorm[i] U += complex(beta[i] * cf * ((1j)**m[0]) * vnmpocnp(r, f, n, m)[0][0][0] * cmath.exp(1j * m[0] * phi)) return 2.0 * U
def test_vnmpocnp(self): data = h5py.File('refVnmpo.h5', 'r') ref = data['ref'].value r = data['r'].value f = data['f'].value n = data['n'].value m = data['m'].value data.close() out = vnmpocnp(r, f, n, m) self.assertTrue(out.shape[0] == r.size) self.assertTrue(out.shape[1] == r.size) self.assertTrue(out.shape[2] == n.size) err = norm((out - ref).ravel()) self.assertTrue(err < self.max_enorm)
def make_pol_grid(self, r_sp=None, ph_sp=None, f_sp=None, min_r=1e-9): r"""Make a polar grid for the complex point-spread function. The complex point-spread function is .. math:: U(r, \phi, f) = 2 \sum_{n, m} \beta_{n}^{m} \sqrt{n + 1} i^{m} V_n^m(r, f) \exp(im\phi). See Eq. (4) in [A2015]_. Parameters ---------- - `r_sp`: `numpy` array of the radial coordinate :math:`r` - `ph_sp`: `numpy` array of the azimuthal coordinate :math:`\phi` - `f_sp`: `numpy` array of complex numbers for the defocus parameter, see [J2002]_, [B2008]_, [H2010]_ - `min_r`: float, optional threshold to avoid division by zero in the image plane 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>`__. .. [J2002] A. J. E. M. Janssen, "Extended Nijboer–Zernike approach for the computation of optical point-spread functions," J. Opt. Soc. Am. A 19, 849–857 (2002). `doi <http://dx.doi.org/10.1364/JOSAA.19.000849>`__. .. [B2008] J. Braat, S. van Haver, A. Janssen, P. Dirksen, Chapter 6 Assessment of optical systems by means of point-spread functions, In: E. Wolf, Editor(s), Progress in Optics, Elsevier, 2008, Volume 51, Pages 349-468, ISSN 0079-6638, ISBN 9780444532114. `doi <http://dx.doi.org/10.1016/S0079-6638(07)51006-1>`__. .. [H2010] S. van Haver, The Extended Nijboer-Zernike Diffraction Theory and its Applications (Ph.D. thesis, Delft University of Technology, The Netherlands, 2010). `doi <http://resolver.tudelft.nl/uuid:8d96ba75-24da-4e31-a750-1bc348155061>`__. """ r_sp = self._numpify(r_sp, np.float).ravel(order='F') ph_sp = self._numpify(ph_sp, np.float).ravel(order='F') f_sp = self._numpify(f_sp, np.complex).ravel(order='F') # remove nans due to r = 0.0 r_sp = self._trim_r(r_sp, min_r) Ugrid = np.zeros((r_sp.size, ph_sp.size, f_sp.size, self.czern.nk), order='F', dtype=np.complex) Vnm = vnmpocnp(r_sp, f_sp, self.czern.ntab, self.czern.mtab) Cnm = np.zeros((ph_sp.size, self.czern.nk), order='F', dtype=np.complex) for k in range(self.czern.nk): m = self.czern.mtab[k] Cnm[:, k] = 2.0 * self.czern.coefnorm[k] * ( (1j)**m) * np.exp(1j * m * ph_sp) for k in range(self.czern.nk): for f in range(f_sp.size): v = Vnm[:, f, k].reshape((Vnm.shape[0], 1)) c = Cnm[:, k].reshape((1, Cnm.shape[0])) Ugrid[:, :, f, k] = np.kron(c, v) assert (np.all(np.isfinite(Ugrid))) self.Ugrid = Ugrid self.Vnm = Vnm self.Cnm = Cnm