def test_rotate_zonal_harmonics_random(self): """Tests the outputs of test_rotate_zonal_harmonics.""" dtype = tf.float64 max_band = 2 zonal_coeffs = tf.constant(np.random.uniform(-1.0, 1.0, size=[3]), dtype=dtype) tensor_size = np.random.randint(3) tensor_shape = np.random.randint(1, 10, size=(tensor_size)).tolist() theta = tf.constant(np.random.uniform(0.0, np.pi, size=tensor_shape + [1]), dtype=dtype) phi = tf.constant(np.random.uniform(0.0, 2.0 * np.pi, size=tensor_shape + [1]), dtype=dtype) rotated_zonal_coeffs = spherical_harmonics.rotate_zonal_harmonics( zonal_coeffs, theta, phi) zonal_coeffs = spherical_harmonics.tile_zonal_coefficients( zonal_coeffs) l, m = spherical_harmonics.generate_l_m_permutations(max_band) l = tf.broadcast_to(l, tensor_shape + l.shape.as_list()) m = tf.broadcast_to(m, tensor_shape + m.shape.as_list()) theta_zero = tf.constant(0.0, shape=tensor_shape + [1], dtype=dtype) phi_zero = tf.constant(0.0, shape=tensor_shape + [1], dtype=dtype) gt = zonal_coeffs * spherical_harmonics.evaluate_spherical_harmonics( l, m, theta_zero, phi_zero) gt = tf.reduce_sum(input_tensor=gt, axis=-1) pred = rotated_zonal_coeffs * spherical_harmonics.evaluate_spherical_harmonics( l, m, theta + theta_zero, phi + phi_zero) pred = tf.reduce_sum(input_tensor=pred, axis=-1) self.assertAllClose(gt, pred)
def test_evaluate_spherical_harmonics_exception_m_raised(self): """Tests that an exception is raised when m is not in the expected range.""" l = np.random.randint(1, 4, size=(1, )) m = np.random.randint(5, 10, size=(1, )) theta = np.random.uniform(0.0, np.pi, size=(1, )) phi = np.random.uniform(0.0, 2.0 * np.pi, size=(1, )) with self.assertRaises(tf.errors.InvalidArgumentError): self.evaluate( spherical_harmonics.evaluate_spherical_harmonics( l, m, theta, phi)) m = np.random.randint(-10, -5, size=(1, )) with self.assertRaises(tf.errors.InvalidArgumentError): self.evaluate( spherical_harmonics.evaluate_spherical_harmonics( l, m, theta, phi))
def test_evaluate_spherical_harmonics_exception_phi_raised(self): """Tests exceptions on the values of phi.""" l = np.random.randint(1, 4, size=(1, )) m = np.random.randint(5, 10, size=(1, )) theta = np.random.uniform(0.0, np.pi, size=(1, )) phi = np.random.uniform(2.0 * np.pi + sys.float_info.epsilon, 4.0 * np.pi, size=(1, )) with self.assertRaises(tf.errors.InvalidArgumentError): self.evaluate( spherical_harmonics.evaluate_spherical_harmonics( l, m, theta, phi)) phi = np.random.uniform(-2.0 * np.pi, 0.0 - sys.float_info.epsilon, size=(1, )) with self.assertRaises(tf.errors.InvalidArgumentError): self.evaluate( spherical_harmonics.evaluate_spherical_harmonics( l, m, theta, phi))
def test_evaluate_spherical_harmonics_jacobian_random(self): """Test the Jacobian of the evaluate_spherical_harmonics function.""" tensor_size = np.random.randint(3) tensor_shape = np.random.randint(1, 5, size=(tensor_size)).tolist() l_init = np.random.randint(5, 10, size=tensor_shape) l_init = np.expand_dims(l_init, axis=-1) m_init = np.random.randint(0, 4, size=tensor_shape) m_init = np.expand_dims(m_init, axis=-1) theta_init = np.random.uniform(0.0, np.pi, size=tensor_shape) theta_init = np.expand_dims(theta_init, axis=-1) phi_init = np.random.uniform(0.0, 2.0 * np.pi, size=tensor_shape) phi_init = np.expand_dims(phi_init, axis=-1) theta = tf.convert_to_tensor(value=theta_init) phi = tf.convert_to_tensor(value=phi_init) y = spherical_harmonics.evaluate_spherical_harmonics( l_init, m_init, theta, phi) self.assert_jacobian_is_correct(theta, theta_init, y) self.assert_jacobian_is_correct(phi, phi_init, y)
def test_evaluate_spherical_harmonics_jacobian_random(self): """Test the Jacobian of the evaluate_spherical_harmonics function.""" tensor_size = np.random.randint(3) tensor_shape = np.random.randint(1, 5, size=(tensor_size)).tolist() l_init = np.random.randint(5, 10, size=tensor_shape) l_init = np.expand_dims(l_init, axis=-1) m_init = np.random.randint(0, 4, size=tensor_shape) m_init = np.expand_dims(m_init, axis=-1) theta_init = np.random.uniform(0.0, np.pi, size=tensor_shape) theta_init = np.expand_dims(theta_init, axis=-1) phi_init = np.random.uniform(0.0, 2.0 * np.pi, size=tensor_shape) phi_init = np.expand_dims(phi_init, axis=-1) # Wrap these in identities because some assert_* ops look at the constant # tensor value and mark it as unfeedable. theta = tf.identity(tf.convert_to_tensor(value=theta_init)) phi = tf.identity(tf.convert_to_tensor(value=phi_init)) y = spherical_harmonics.evaluate_spherical_harmonics( l_init, m_init, theta, phi) self.assert_jacobian_is_correct(theta, theta_init, y) self.assert_jacobian_is_correct(phi, phi_init, y)
def test_evaluate_spherical_harmonics_preset(self): tensor_size = np.random.randint(3) tensor_shape = np.random.randint(1, 10, size=(tensor_size)).tolist() pt_3d = tf.convert_to_tensor(value=np.random.uniform( size=tensor_shape + [3])) pt_3d = tf.math.l2_normalize(pt_3d, axis=-1) x, y, z = tf.unstack(pt_3d, axis=-1) x = tf.expand_dims(x, axis=-1) y = tf.expand_dims(y, axis=-1) z = tf.expand_dims(z, axis=-1) pt_spherical = math_helpers.cartesian_to_spherical_coordinates(pt_3d) _, theta, phi = tf.unstack(pt_spherical, axis=-1) theta = tf.expand_dims(theta, axis=-1) phi = tf.expand_dims(phi, axis=-1) ones = tf.ones_like(z) with self.subTest(name="l_0_m_0"): l = tf.zeros_like(theta, dtype=tf.int32) m = tf.zeros_like(theta, dtype=tf.int32) val = spherical_harmonics.evaluate_spherical_harmonics( l, m, theta, phi) gt = ones / (2.0 * tf.sqrt(ones * np.pi)) self.assertAllClose(val, gt) with self.subTest(name="l_1_m_-1"): l = tf.ones_like(theta, dtype=tf.int32) m = -tf.ones_like(theta, dtype=tf.int32) val = spherical_harmonics.evaluate_spherical_harmonics( l, m, theta, phi) gt = -tf.sqrt(3.0 * ones) * y / (2.0 * tf.sqrt(ones * np.pi)) self.assertAllClose(val, gt) with self.subTest(name="l_1_m_0"): l = tf.ones_like(theta, dtype=tf.int32) m = tf.zeros_like(theta, dtype=tf.int32) val = spherical_harmonics.evaluate_spherical_harmonics( l, m, theta, phi) gt = (tf.sqrt(3.0 * ones) * z) / (2.0 * tf.sqrt(ones * np.pi)) self.assertAllClose(val, gt) with self.subTest(name="l_1_m_1"): l = tf.ones_like(theta, dtype=tf.int32) m = tf.ones_like(theta, dtype=tf.int32) val = spherical_harmonics.evaluate_spherical_harmonics( l, m, theta, phi) gt = -tf.sqrt(3.0 * ones) * x / (2.0 * tf.sqrt(ones * np.pi)) self.assertAllClose(val, gt) with self.subTest(name="l_2_m-2"): l = 2 * tf.ones_like(theta, dtype=tf.int32) m = -2 * tf.ones_like(theta, dtype=tf.int32) val = spherical_harmonics.evaluate_spherical_harmonics( l, m, theta, phi) gt = tf.sqrt(15.0 * ones) * y * x / (2.0 * tf.sqrt(ones * np.pi)) self.assertAllClose(val, gt) with self.subTest(name="l_2_m_-1"): l = 2 * tf.ones_like(theta, dtype=tf.int32) m = -tf.ones_like(theta, dtype=tf.int32) val = spherical_harmonics.evaluate_spherical_harmonics( l, m, theta, phi) gt = -tf.sqrt(15.0 * ones) * y * z / (2.0 * tf.sqrt(ones * np.pi)) self.assertAllClose(val, gt) with self.subTest(name="l_2_m_0"): l = 2 * tf.ones_like(theta, dtype=tf.int32) m = tf.zeros_like(theta, dtype=tf.int32) val = spherical_harmonics.evaluate_spherical_harmonics( l, m, theta, phi) gt = tf.sqrt(5.0 * ones) * (3.0 * z * z - ones) / (4.0 * tf.sqrt(ones * np.pi)) self.assertAllClose(val, gt) with self.subTest(name="l_2_m_1"): l = 2 * tf.ones_like(theta, dtype=tf.int32) m = tf.ones_like(theta, dtype=tf.int32) val = spherical_harmonics.evaluate_spherical_harmonics( l, m, theta, phi) gt = -tf.sqrt(15.0 * ones) * x * z / (2.0 * tf.sqrt(ones * np.pi)) self.assertAllClose(val, gt) with self.subTest(name="l_2_m_2"): l = 2 * tf.ones_like(theta, dtype=tf.int32) m = 2 * tf.ones_like(theta, dtype=tf.int32) val = spherical_harmonics.evaluate_spherical_harmonics( l, m, theta, phi) gt = tf.sqrt( 15.0 * ones) * (x * x - y * y) / (4.0 * tf.sqrt(ones * np.pi)) self.assertAllClose(val, gt)
def evaluate_spherical_harmonics_fn(theta, phi): return spherical_harmonics.evaluate_spherical_harmonics( l_init, m_init, theta, phi)