def test_eigenmask1(self): m = wave.eigenmask((1, 13), (1, 2), betamax=1.5) m1 = wave.eigenmask1(13, (1, 2), betamax=1.5) self.allclose(m[:, 0, :], m1) m = wave.eigenmask((1, 13), 2, betamax=1.5) m1 = wave.eigenmask1(13, 2, betamax=1.5) self.allclose(m[0, :], m1) m = wave.eigenmask((1, 13), 2, betamax=1.5) m1 = wave.eigenmask1(13, 2, betamax=1.5) self.allclose(m[0, :], m1)
def test_mask2indices1(self): mask = wave.eigenmask((1, 12), (1, 2), betamax=1.8) indices = wave.mask2indices(mask, (1, 2)) mask1 = wave.eigenmask1(12, (1, 2), betamax=1.8) indices1 = wave.mask2indices1(mask1, (1, 2)) self.allclose(indices[0][..., 1], indices1[0]) self.allclose(indices[1][..., 1], indices1[1]) mask = wave.eigenmask((1, 12), 2, betamax=1.8) indices = wave.mask2indices(mask, 2) mask1 = wave.eigenmask1(12, 2, betamax=1.8) indices1 = wave.mask2indices1(mask1, 2) self.allclose(indices[..., 1], indices1)
def test_mask2betax1(self): mask = wave.eigenmask((12, 1), (1, 2), 1.8) beta = wave.mask2beta(mask, (1, 2)) mask1 = wave.eigenmask1(12, (1, 2), 1.8) betax1 = wave.mask2betax1(mask1, (1, 2)) self.allclose(beta[0], np.abs(betax1[0])) self.allclose(beta[1], np.abs(betax1[1])) mask = wave.eigenmask((12, 1), 2, 1.8) beta = wave.mask2beta(mask, 2) mask1 = wave.eigenmask1(12, 2, 1.8) betax1 = wave.mask2betax1(mask1, 2) self.allclose(beta, np.abs(betax1))
def test_mask2indices(self): mask = wave.eigenmask((4, 3), (1, 2), 1.8) indices = wave.mask2indices(mask, (1, 2)) self.allclose(indices[0], self.eigenindices[0]) self.allclose(indices[1], self.eigenindices[1]) indices = wave.mask2indices(mask[1], 2) self.allclose(indices, self.eigenindices[1])
def test_mask2beta(self): mask = wave.eigenmask((4, 3), (1, 2), 1.8) beta = wave.mask2beta(mask, (1, 2)) self.allclose(beta[0], self.beta[0][mask[0]]) self.allclose(beta[1], self.beta[1][mask[1]]) beta = wave.mask2beta(mask[1], 2) self.allclose(beta, self.beta[1][mask[1]]) self.isfloat(beta)
def test_mask2phi(self): mask = wave.eigenmask((4, 3), (1, 2), 1.8) phi = wave.mask2phi(mask, (1, 2)) self.allclose(phi[0], self.phi[mask[0]]) self.allclose(phi[1], self.phi[mask[1]]) phi = wave.mask2phi(mask[1], 2) self.allclose(phi, self.phi[mask[1]]) self.isfloat(phi)
def ffield2modes(ffield, k0, betamax=BETAMAX): k0 = np.asarray(k0) mask = eigenmask(ffield.shape[-2:], k0, betamax) if k0.ndim == 0: return mask, np.moveaxis(ffield[..., mask], -2, -1) else: return mask, tuple((np.moveaxis(ffield[..., i, :, :, :][..., mask[i]], -2, -1) for i in range(len(k0))))
def layer_mat3d(k0, d, epsv, epsa, mask=None, method="4x4"): """Computes characteristic matrix of a single layer M=F.P.Fi, Numpy broadcasting rules apply Parameters ---------- k0 : float or sequence of floats A scalar or a vector of wavenumbers d : array_like Layer thickness epsv : array_like Epsilon eigenvalues. epsa : array_like Optical axes orientation angles (psi, theta, phi). method : str, optional Either a 4x4 or 4x4_1 Returns ------- cmat : ndarray Characteristic matrix of the layer. """ if method not in ("4x4", "4x4_1", "2x2"): raise ValueError("Unsupported method: '{}'".format(method)) k0 = np.asarray(k0) shape = epsv.shape[-3], epsv.shape[-2] if mask is None: mask = eigenmask(shape, k0) betas = eigenbeta(shape, k0) phis = eigenphi(shape, k0) indices = eigenindices(shape, k0) else: betas = mask2beta(mask, k0) phis = mask2phi(mask, k0) indices = mask2indices(mask, k0) if k0.ndim == 0: return _layer_mat3d(k0, d, epsv, epsa, mask, betas, phis, indices, method) else: out = (_layer_mat3d(k0[i], d, epsv, epsa, mask[i], betas[i], phis[i], indices[i], method) for i in range(len(k0))) return tuple(out)
def field2modes(field, k0, betamax=BETAMAX): """Converts 2D field array to modes array. Parameters ---------- field : ndarray or tuple of ndarrays Input field array (or tuple of input fields for each wavenumber). The shape of the input arrays must be (...,4,:,:) representing. k0 : float or a sequence of floats Defines the wavenumber. Fol multi-wavelength data, this must be a sequence of wawenumbers betamax : float, optional The beta cutoff parameter. Returns ------- mask, modes : ndarray, ndarray or ndarray, tuple of ndarrays For a single-wavelength data it returns the mask array specifying the mode indices and modes coefficients array. For multi-wavelength data the modes is a tuple of ndarrays for each of the wavelengths. Length of the mask in this case equals length of the wavenumbers. """ if isinstance(field, tuple): out = tuple( (field2modes(field[i], k0[i], betamax) for i in range(len(field)))) mask = tuple(o[0] for o in out) modes = tuple(o[1] for o in out) return mask, modes f = fft2(field) k0 = np.asarray(k0) mask = eigenmask(f.shape[-2:], k0, betamax) if k0.ndim == 0: return mask, np.moveaxis(f[..., mask], -2, -1) else: return mask, tuple((np.moveaxis(f[..., i, :, :, :][..., mask[i]], -2, -1) for i in range(len(k0))))
def test_eigenmask(self): m = self.beta < 1.8 out = wave.eigenmask(self.shape, self.ks, betamax=1.8) self.allclose(out, m)
def _field2modes(field, k0, betamax=BETAMAX): f = fft2(field) mask = eigenmask(f.shape[-2:], k0, betamax) f = f[mask] return np.moveaxis(f, -2, -1)