def profile(self, z, f, dx=1.): """ Beam's complex amplitude at an axial distance z from waist. Plane lies perpendicular to z axis and has the same shape as f. ========Input========= z : Axial distance from waist f : 2D Array defining the output array shape dx : Pixel pitch (default value is unit of measurement) ========Raises======== ========Output======== g : 2D complex array (complex amplitude at an axial distance z from waist centered at z axis) """ n, m = tl.shape(f) x = tl.arange(-m * dx / 2, m * dx / 2, dx) y = tl.arange(-n * dx / 2, n * dx / 2, dx) X, Y = tl.meshgrid(x, y) g = self.value(X, Y, z) return g
def profile(self, z, f, dx=1.): """ Beam's complex amplitude at an axial distance z from waist. Plane lies perpendicular to z axis and has the same shape as f. ========Input========= z : Axial distance from waist f : 2D Array defining the output array shape dx : Pixel pitch (default value is unit of measurement) ========Raises======== TypeError: If f isn't a 2D array ========Output======== g : 2D complex array (complex amplitude at an axial distance z from waist centered at z axis) """ if (len(tl.shape(f)) != 2): raise TypeError('f must be a 2D array') n, m = tl.shape(f) x = tl.arange(-m * dx / 2, m * dx / 2, dx) y = tl.arange(-n * dx / 2, n * dx / 2, dx) X, Y = tl.meshgrid(x, y) R = tl.sqrt(X**2 + Y**2) g = self.value(R, z) return g
def Lens(F, R, wl, shape, dx=1.): """ ~ Samples the trasmittance function of a thin lens with focal lenght f for a wave with central wavelenght wl with sampling interval dx ========Input========= F : Focal lenght of thin lens R : Radius of the lens wl : Central wavelenght shape : Array shape dx : Sampling interval (default value is unit of measurement) ========Raises========= TypeError : If f isn't a 2D array ========Output======== t : Thin lens complex transmittance """ if (len(shape) != 2): raise TypeError('Shape must be 2D') n, m = shape x = tl.arange(-m * dx / 2, m * dx / 2, dx) y = tl.arange(-n * dx / 2, n * dx / 2, dx) X, Y = tl.meshgrid(x, y) t = tl.exp(-1j * (tl.pi / (wl * F)) * (X**2 + Y**2)) t *= Pupil(R, shape, dx) return t
def FresnelIR(f, z, wl, dx): """ ~ Propagates f in free space sampling the Impulse Response Voelz D. Computational Fourier Optics: A MATLAB Tutorial. 2011. ========Input========= f : Input complex amplitude profile (2D complex array) z : Propagation distance wl : Central wavelenght of the field dx : Sampling interval (default value is unit of measurement) ========Output======== h : Propagated complex amplitude profile (2D complex array) """ n, m = tl.shape(f) Lx = dx * n Ly = dx * m F = FFT2(f) x = tl.arange(-Lx / 2, Lx / 2, dx) y = tl.arange(-Ly / 2, Ly / 2, dx) X, Y = tl.meshgrid(x, y) g = tl.exp(1j * tl.pi / (wl * z) * (X**2 + Y**2)) / (1j * wl * z) G = FFT2(g) * dx * dx h = IFFT2(F * G) return h
def FresnelTF(f, z, wl, dx): """ ~ Propagates f in free space sampling the Transfer Function Voelz D. Computational Fourier Optics: A MATLAB Tutorial. 2011. ========Input========= f : Input complex amplitude profile (2D complex array) z : Propagation distance wl : Central wavelenght of the field dx : Sampling interval (default value is unit of measurement) SBC : Use the source bandwidth criterion for large propagation regime ========Output======== h : Propagated complex amplitude profile (2D complex array) """ n, m = tl.shape(f) Lx = dx * n Ly = dx * m F = FFT2(f) fx = tl.arange(-1 / (2 * dx), 1 / (2 * dx), 1 / Lx) fy = tl.arange(-1 / (2 * dx), 1 / (2 * dx), 1 / Ly) FX, FY = tl.meshgrid(fx, fy) G = tl.exp((-1j * wl * tl.pi * z) * (FX**2 + FY**2)) h = IFFT2(F * G) return h
def Pupil(R, shape, dx=1.): """ ~ Simulates the trasmittance function of a pinhole with radius R ~ This is essentially a circ function ========Input========= R : Radius of pinhole shape : Array shape dx : Sampling interval (default value is unit of measurement) ========Raises========= TypeError: If f isn't a 2D array ========Output======== t : Pinhole transmittance """ if (len(shape) != 2): raise TypeError('f must be a 2D array') n, m = shape x = tl.arange(-m * dx / 2, m * dx / 2, dx) y = tl.arange(-n * dx / 2, n * dx / 2, dx) X, Y = tl.meshgrid(x, y) t = (X**2 + Y**2 <= R**2) * 1. return t
def Tilt(alpha, theta, wl, shape, dx=1.): """ ~ Simulates the trasmittance function of a tilt (a prism for instance) ========Input========= alpha : Tilt polar angle theta : Tilt azimuth angle wl : Central wavelenght shape : Array shape dx : Sampling interval (default value is unit of measurement) ========Raises========= TypeError: If f isn't a 2D array ========Output======== t : Pinhole transmittance """ if (len(shape) != 2): raise TypeError('f must be a 2D array') n, m = shape x = tl.arange(-m * dx / 2, m * dx / 2, dx) y = tl.arange(-n * dx / 2, n * dx / 2, dx) X, Y = tl.meshgrid(x, y) t = tl.exp(2j * tl.pi / wl * (X * tl.cos(theta) + Y * tl.sin(theta)) * tl.tan(alpha)) return t
def Fraunhofer(f, z, wl, dx=1.): """ ~ Propagates input 2D array in free space using the Fraunhofer propagator Voelz D. Computational Fourier Optics: A MATLAB Tutorial. 2011. ========Input========= f : Input complex amplitude profile (2D complex array) z : Propagation distance wl : Central wavelenght of the field dx : Sampling interval (default value is unit of measurement) ========Output======== g : Propagated complex amplitude profile (2D complex array) oL : Observation plane side lenght """ n, m = tl.shape(f) oL = wl * z / dx # Observation plane side lenght odx = oL / m ody = oL / n # Observation plane sample interval x = tl.arange(-oL / 2, oL / 2, odx) y = tl.arange(-oL / 2, oL / 2, ody) X, Y = tl.meshgrid(x, y) g = -1j / (wl * z) * tl.exp(1j * tl.pi / (wl * z) * (X**2 + Y**2)) g = g * FFT2(f) * dx * dx return g, oL
def Fresnel2S(f, z, wl, L1, L2): """ ~ Propagates input 2D array in free space using the two-step Fresnel propagator Voelz D. Computational Fourier Optics: A MATLAB Tutorial. 2011. ========Input========= f : Input complex amplitude profile (2D complex array) z : Propagation distance wl : Central wavelenght of the field L1 : Input sample plane side lenght L2 : Output sample plane side lenght ========Output======== h : Propagated complex amplitude profile (2D complex array) """ if (tl.ndim(f) != 2): raise TypeError("Input array must be a 2D square array") m, n = tl.shape(f) if (m != n): raise ValueError("Input array must be a 2D square array") k = 2 * tl.pi / wl # Source plane dx1 = L1 / m x1 = tl.arange(-L1 / 2., L1 / 2., dx1) X, Y = tl.meshgrid(x1, x1) F = f * tl.exp(1j * k / (2. * z * L1) * (L1 - L2) * (X**2 + Y**2)) F = tl.fft.fft2(tl.fft.fftshift(F)) # Dummy plane fx1 = tl.arange(-1. / (2 * dx1), 1. / (2 * dx1), 1. / L1) fx1 = tl.fft.fftshift(fx1) FX1, FY1 = tl.meshgrid(fx1, fx1) G = F * tl.exp(-1j * tl.pi * wl * z * L1 / L2 * (FX1**2 + FY1**2)) g = tl.fft.ifftshift(tl.fft.ifft2(G)) # Observation plane dx2 = L2 / m x2 = tl.arange(-L2 / 2., L2 / 2., dx2) X, Y = tl.meshgrid(x2, x2) g = (L2 / L1) * g * tl.exp(-1j * k / (2. * z * L2) * (L1 - L2) * (X**2 + Y**2)) g = g * (dx1 / dx2)**2 return g
def GetRBW(f, dx=1., dy=None, p=0.98): """ ~ Approximately calculates full radial bandwidth ~ This is not a verified numerical method just something I made up ========Input========= f : Input 2D array p : Effectiveness parameter dx : Horizontal sampling interval (Default value is unit of measurement) dy : Vertical sampling interval (Default for square sampling) ========output======== RBW : Full radial bandwidth. """ if (dy == None): dy = dx n, m = tl.shape(f) M = max([n, m]) F = FFT2(f) P = Power(F) # Total power fr = tl.arange(1, M + 1) # Radial frequency in pixels Pr = [Power(F * Ellipse(fri, fri, (n, m), use_pxc=True)) for fri in fr ] # Power as function of radial distance in the Fourier domain RBW = 2 * max(fr[Pr <= p * P]) * max([1. / dx, 1. / dy]) return RBW
def FresnelCS(f, z, wl, dx=1., SBC=False): """ ~ Propagates input 2D array in free space using the critical sampling criterion ~ Samples either the Impulse Response or the Transfer Function given the critic sampling criterion Voelz D. Computational Fourier Optics: A MATLAB Tutorial. 2011. ========Input========= f : Input complex amplitude profile (2D complex array) z : Propagation distance wl : Central wavelenght of the field dx : Sampling interval (default value is unit of measurement) SBC : Use the source bandwidth criterion for large propagation regime ========Output======== h : Propagated complex amplitude profile (2D complex array) """ n, m = tl.shape(f) # Array dimensions Lx = dx * m Ly = dx * n # Source plane side lenghts zc = dx * Lx / wl # Critic sampling propagation distance F = FFT2(f) if (SBC): # Check the source bandwidth criterion B = GetRBW(f, dx) SBC = B <= min([Lx, Ly]) / (wl * z) if (abs(z) > zc and not SBC): # Propagating using Impulse Response x = tl.arange(-Lx / 2., Lx / 2., dx) y = tl.arange(-Ly / 2., Ly / 2., dx) X, Y = tl.meshgrid(x, y) g = tl.exp(1j * tl.pi / (wl * z) * (X**2 + Y**2)) / (1j * wl * z) G = FFT2(g) * dx * dx if (abs(z) <= zc): # Propagating using Transfer Function F = 0.5 / dx # Nyquist frequency fx = tl.arange(-F, F, 1. / Lx) fy = tl.arange(-F, F, 1. / Ly) FX, FY = tl.meshgrid(fx, fy) G = tl.exp((-1j * wl * tl.pi * z) * (FX**2 + FY**2)) h = IFFT2(F * G) return h