def test_rotation_sh_basis_z_axis_real(): rot_angle = np.pi / 2 n_max = 2 coords_x = Coordinates(1, 0, 0) coords_y = Coordinates(0, -1, 0) reference = np.squeeze( spharpy.spherical.spherical_harmonic_basis_real(n_max, coords_x)) rot_mat = spharpy.transforms.rotation_z_axis_real(n_max, rot_angle) sh_vec_x = spharpy.spherical.spherical_harmonic_basis_real(n_max, coords_y) sh_vec_rotated = np.squeeze(rot_mat @ sh_vec_x.T) np.testing.assert_almost_equal(sh_vec_rotated, reference)
def test_rotation_sh_basis_z_axis_complex(): rot_angle = np.pi / 2 n_max = 2 theta = np.asarray(np.pi / 2)[np.newaxis] phi_x = np.asarray(0.0)[np.newaxis] phi_y = np.asarray(np.pi / 2)[np.newaxis] coords_x = Coordinates(1, 0, 0) coords_y = Coordinates(0, -1, 0) reference = spherical_harmonic_basis(n_max, coords_x).T.conj() rot_mat = transforms.rotation_z_axis(n_max, rot_angle) sh_vec_x = spherical_harmonic_basis(n_max, coords_y) sh_vec_rotated = rot_mat @ sh_vec_x.T.conj() np.testing.assert_almost_equal(sh_vec_rotated, reference)
def test_spherical_harmonic(): Nmax = 1 theta = np.array([np.pi / 2, np.pi / 2, 0], dtype='double') phi = np.array([0, np.pi / 2, 0], dtype='double') rad = np.ones(3, dtype=np.double) coords = Coordinates.from_spherical(rad, theta, phi) Y = np.array([[ 2.820947917738781e-01 + 0.000000000000000e+00j, 3.454941494713355e-01 + 0.000000000000000e+00j, 2.991827511286337e-17 + 0.000000000000000e+00j, -3.454941494713355e-01 + 0.000000000000000e+00j ], [ 2.820947917738781e-01 + 0.000000000000000e+00j, 2.115541521371041e-17 - 3.454941494713355e-01j, 2.991827511286337e-17 + 0.000000000000000e+00j, -2.115541521371041e-17 - 3.454941494713355e-01j ], [ 2.820947917738781e-01 + 0.000000000000000e+00j, 0.000000000000000e+00 + 0.000000000000000e+00j, 4.886025119029199e-01 + 0.000000000000000e+00j, 0.000000000000000e+00 + 0.000000000000000e+00j ]], dtype=complex) basis = sh.spherical_harmonic_basis(Nmax, coords) np.testing.assert_allclose(Y, basis, atol=1e-13)
def interior_stabilization_points(kr_max, resolution_factor=1): """ Find points inside the interior domain of an open spherical microphone array that stabilize the array array response at the eigenfrequencies of the array. The algorithm is based on _[1] and implemented following the Matlab code provided by Gilles Chardon on his homepage at _[2]. The stabilization points are independent of the sampling of the sphere and can therefore be combined with arbitrary spherical samplings. Parameters ---------- kr_max : float The maximum kr value to be considered. This will define the upper frequency limit of the array. resolution_factor : int Factor to increase the spatial resolution of the grid used to estimate the stabilization points. Returns ------- sampling_interior : Coordinates Coordinates of the stabilization points References ---------- .. [1] G. Chardon, W. Kreuzer, und M. Noisternig, "Design of spatial microphone arrays for sound field interpolation", IEEE Journal of Selected Topics in Signal Processing .. [2] https://gilleschardon.fr/jstsp_array/ """ x, y, z = find_interior_points(kr_max, resolution_factor=resolution_factor) sampling_interior = Coordinates(x, y, z) return sampling_interior
def test_spherical_harmonics_real(): n_max = 10 theta = np.array([np.pi / 2, np.pi / 2, 0, np.pi / 2], dtype='double') phi = np.array([0, np.pi / 2, 0, np.pi / 4], dtype='double') rad = np.ones(4) coords = Coordinates.from_spherical(rad, theta, phi) reference = read_2d_matrix_from_csv('./tests/data/sh_basis_real.csv') basis = sh.spherical_harmonic_basis_real(n_max, coords) np.testing.assert_allclose(basis, reference, atol=1e-13)
def test_spherical_harmonic_n10(): Nmax = 10 theta = np.array([np.pi / 2, np.pi / 2, 0], dtype='double') phi = np.array([0, np.pi / 2, 0], dtype='double') n_points = len(theta) with patch.multiple(Coordinates, azimuth=phi, elevation=theta, n_points=n_points) as patched_vals: coords = Coordinates() Y = np.genfromtxt('./tests/data/sh_basis_cplx_n10.csv', delimiter=',', dtype=np.complex) basis = sh.spherical_harmonic_basis(Nmax, coords) np.testing.assert_allclose(Y, basis, atol=1e-13)
def test_orthogonality(): """ Check if the orthonormality condition of the spherical harmonics is fulfilled """ n_max = 82 theta = np.array([np.pi / 2, np.pi / 2, 0, np.pi / 2], dtype='double') phi = np.array([0, np.pi / 2, 0, np.pi / 4], dtype='double') n_points = phi.size n_points = len(theta) with patch.multiple(Coordinates, azimuth=phi, elevation=theta, n_points=n_points) as patched_vals: coords = Coordinates() basis = sh.spherical_harmonic_basis(n_max, coords) inner = (basis @ np.conjugate(basis.T)) fact = 4 * np.pi / (n_max + 1)**2 orth = np.diagonal(fact * inner) np.testing.assert_allclose(orth, np.ones(n_points), rtol=1e-15)
def test_spherical_harmonic_basis_gradient_real(): n_max = 15 theta = np.array([np.pi / 2, np.pi / 2, 0, np.pi / 2, np.pi / 4]) phi = np.array([0, np.pi / 2, 0, np.pi / 4, np.pi / 4]) n_points = np.size(theta) with patch.multiple(Coordinates, azimuth=phi, elevation=theta, n_points=n_points): coords = Coordinates() grad_ele, grad_azi = \ sh.spherical_harmonic_basis_gradient_real(n_max, coords) desire_ele = np.genfromtxt('./tests/data/Y_grad_real_ele.csv', dtype=np.complex, delimiter=',') npt.assert_allclose(grad_ele, desire_ele, rtol=1e-10, atol=1e-10) desire_azi = np.genfromtxt('./tests/data/Y_grad_real_azi.csv', dtype=np.complex, delimiter=',') npt.assert_allclose(grad_azi, desire_azi, rtol=1e-10, atol=1e-10)