Commit 4140124d authored by Leon Merten Lohse's avatar Leon Merten Lohse
Browse files

documentation for vacuum propagators

parent 27e2e560
Pipeline #214686 passed with stages
in 1 minute and 3 seconds
# This program is public domain
"""
Diffraction / Wavefield propagation through vacuum and homogeneous media.
Diffraction/Wavefield propagation in vacuum and homogeneous media.
"""
import numpy as np
from scipy.fft import fftn, ifftn
from . import hankel
from .misc import fftfreqn, crop, squaresum
__all__ = [
"FresnelPropagatorCS",
"FTConvolutionPropagator",
"FresnelTFPropagator",
"FresnelIRPropagator",
"ASMPropagator",
]
def _verify_fresnel_numbers(fresnel_numbers, ndim):
fresnel_numbers = np.asarray(fresnel_numbers)
......@@ -28,6 +35,38 @@ def _verify_fresnel_numbers(fresnel_numbers, ndim):
class FresnelPropagatorCS:
"""
Create a callable Fresnel propagator for circular-symmetric fields.
Parameters
----------
nsamples : int
The number of sampling points.
fresnel_numbers : array
List of Fresnel numbers corresponding to different propagation distances.
npad : float, optional
Padding factor.
Returns
-------
f : FresnelPropagatorCS
Callable object ``f(u)`` to propagate the wavefield ``u``.
Notes
-----
If ``ndist = fresnel_numbers.shape[0]``, the number of propagation distances, is greater than one, ``f(u)`` will
return a 2-dimensional array of dimension ``ndist`` x ``nsamples``. Otherwise it will return a 1-dimensional array.
References
----------
.. [1] M. Guizar-Sicairos and J. C. Gutiérrez-Vega, “Computation of quasi-discrete hankel transforms of integer
order forpropagating optical wave fields,” JOSA A21, 53–58 (2004).
Examples
--------
TODO(Leon): add example
"""
def __init__(self, nsamples, fresnel_numbers, npad=1):
# TODO(Leon): verify input
......@@ -57,6 +96,19 @@ class FresnelPropagatorCS:
return kern
def __call__(self, u):
"""
Propagate a signal.
Parameters
----------
u : array
The wavefield to propagate.
Returns
-------
out : ndarray
The propagated wavefield.
"""
u = np.asarray(u)
if np.ndim(u) != 1 or u.shape[0] != self._nsamples:
......@@ -87,9 +139,21 @@ class FresnelPropagatorCS:
class FTConvolutionPropagator:
"""
Base class for propagation methods that are based on Fourier-transform (FT) convolutions.
Base class for creating callable Fourier-Transform convolution propagators.
This class is not intended to be used directly and does nothing.
Parameters
----------
shape : tuple
Shape of input wavefields.
npad : array, optional
Padding factor.
Returns
-------
f : FTConvolutionPropagator
Callable object ``f(u)`` to propagate the wavefield ``u``.
"""
def __init__(self, shape, npad):
......@@ -108,6 +172,19 @@ class FTConvolutionPropagator:
self._ndist = 1
def __call__(self, u, workers=-1):
"""
Propagate a signal.
Parameters
----------
u : array
The wavefield to propagate.
Returns
-------
out : ndarray
The propagated wavefield.
"""
u = np.asarray(u)
if u.shape != self._shape:
......@@ -137,7 +214,40 @@ class FTConvolutionPropagator:
class FresnelTFPropagator(FTConvolutionPropagator):
"""
Fresnel Transfer Function (Fres-TF) method.
Create a callable Fresnel-transfer-function (Fres-TF) propagator.
Parameters
----------
shape : tuple
Shape of input wavefields.
fresnel_numbers: array
List of Fresnel numbers corresponding to different propagation distances.
npad : array, optional
Padding factor.
Returns
-------
f : FresnelTFPropagator
Callable object ``f(u)`` to propagate the wavefield ``u``.
Notes
-----
If ``ndist = fresnel_numbers.shape[0]``, the number of propagation distances, is greater than one, ``f(u)`` will
return a 2-dimensional array of dimension ``ndist`` x ``shape``. Otherwise the output will match the input shape.
See Also
--------
FresnelIRPropagator : Fres-IR propagator
References
----------
.. [1] J. Goodman, "Introduction to Fourier Optics" (W.H. Freeman, New York, NY, 2017), 4th ed
.. [2] W. Zhang, H. Zhang, C. J. Sheppard, and G. Jin, “Analysis of numerical diffraction calculation methods:
from theperspective of phase space optics and the sampling theorem,” JOSA A37, 1748–1766 (2020).
Examples
--------
TODO(Leon): add example
"""
def __init__(self, shape, fresnel_numbers, npad=2):
......@@ -176,7 +286,42 @@ def _gridn(n):
class FresnelIRPropagator(FTConvolutionPropagator):
"""
Fresnel Impulse Response (Fres-IR) method. Goodman calls this the "Convolution approach".
Create a callable Fresnel-impulse-response (Fres-IR) propagator.
Goodman calls this the "Convolution Approach".
Parameters
----------
shape : tuple
Shape of input wavefields.
fresnel_numbers: array
List of Fresnel numbers corresponding to different propagation distances.
npad : array, optional
Padding factor.
Returns
-------
f : FresnelIRPropagator
Callable object ``f(u)`` to propagate the wavefield ``u``.
Notes
-----
If ``ndist = fresnel_numbers.shape[0]``, the number of propagation distances, is greater than one, ``f(u)`` will
return a 2-dimensional array of dimension ``ndist`` x ``shape``. Otherwise the output will match the input shape.
See Also
--------
FresnelTFPropagator : Fres-TF propagator
References
----------
.. [1] J. Goodman, "Introduction to Fourier Optics" (W.H. Freeman, New York, NY, 2017), 4th ed
.. [2] W. Zhang, H. Zhang, C. J. Sheppard, and G. Jin, “Analysis of numerical diffraction calculation methods:
from theperspective of phase space optics and the sampling theorem,” JOSA A37, 1748–1766 (2020).
Examples
--------
TODO(Leon): add example
"""
def __init__(self, shape, fresnel_numbers, npad=2):
......@@ -216,10 +361,52 @@ class FresnelIRPropagator(FTConvolutionPropagator):
class ASMPropagator(FTConvolutionPropagator):
"""
Angular Spectrum Method (ASM).
Create a callable Angular Spectrum Method (ASM) propagator.
Goodman calls this the "Exact Transfer Function approach".
Voelz and Roggeman call this the "Rayleigh-Sommerfeld Transfer Function solution".
Parameters
----------
shape : tuple
Shape of input wavefields.
dperp : tuple
Lateral pixel sizes.
dz : array
Propagation distance(s).
wl : float, optional
Wavelength in units of pixels.
npad : array, optional
Padding factor.
mask_evanescent : bool, optional
Mask evanescent spectral components.
Returns
-------
f : ASMPropagator
Callable object ``f(u)`` to propagate the wavefield ``u``.
Notes
-----
Parameter ``dz`` must be either a scalar or 1d array. If ``ndist = len(dz)``, the number of propagation distances,
is greater than one, ``f(u)`` will return a 2-dimensional array of dimension ``ndist`` x ``shape``. Otherwise
the output will match the input shape.
See Also
--------
FresnelTFPropagator : Fres-TF propagator
FresnelIRPropagator : Fres-IR propagator
References
----------
.. [1] J. Goodman, "Introduction to Fourier Optics" (W.H. Freeman, New York, NY, 2017), 4th ed
.. [2] W. Zhang, H. Zhang, C. J. Sheppard, and G. Jin, “Analysis of numerical diffraction calculation methods:
from the perspective of phase space optics and the sampling theorem,” JOSA A37, 1748–1766 (2020).
Examples
--------
TODO(Leon): add example
"""
_lambda0 = 1.0 # all lengths are in units of the wavelength
......@@ -245,7 +432,6 @@ class ASMPropagator(FTConvolutionPropagator):
self.kernel = self._init_kernel()
def _init_kernel(self):
# construct Rayleigh-Sommerfeld transfer function (Goodman: Fourier Optics, 4.2.3)
f = fftfreqn(self._shape_pad, self._dperp) # spatial frequencies
f2 = squaresum(f)
phase_chirp = np.sqrt(1 / np.square(self._wl) - f2.astype(np.complex))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment