diff --git a/tests/_basis_util.py b/tests/_basis_util.py index 689ca05602..440076366b 100644 --- a/tests/_basis_util.py +++ b/tests/_basis_util.py @@ -4,12 +4,49 @@ from aspire.image import Image from aspire.utils import gaussian_2d, utest_tolerance -from aspire.utils.coor_trans import grid_2d +from aspire.utils.coor_trans import grid_2d, grid_3d +from aspire.utils.misc import gaussian_3d from aspire.utils.random import randn from aspire.volume import Volume -class Steerable2DMixin: +class SteerableMixin: + def testEvaluateExpand(self): + coef1 = randn(self.basis.count, seed=self.seed) + coef1 = coef1.astype(self.dtype) + + x = self.basis.evaluate(coef1) + if isinstance(x, Image) or isinstance(x, Volume): + x = x.asnumpy() + + coef2 = self.basis.expand(x) + if coef2.ndim == 2: + coef2 = coef2[0] + + self.assertTrue(coef1.shape == coef2.shape) + self.assertTrue(np.allclose(coef1, coef2, atol=utest_tolerance(self.dtype))) + + def testAdjoint(self): + u = randn(self.basis.count, seed=self.seed) + u = u.astype(self.dtype) + + Au = self.basis.evaluate(u) + if isinstance(Au, Image) or isinstance(Au, Volume): + Au = Au.asnumpy() + + x = randn(*self.basis.sz, seed=self.seed) + x = x.astype(self.dtype) + + ATx = self.basis.evaluate_t(x) + + Au_dot_x = np.sum(Au * x) + u_dot_ATx = np.sum(u * ATx) + + self.assertTrue(Au_dot_x.shape == u_dot_ATx.shape) + self.assertTrue(np.isclose(Au_dot_x, u_dot_ATx)) + + +class Steerable2DMixin(SteerableMixin): def testIndices(self): ell_max = self.basis.ell_max k_max = self.basis.k_max @@ -99,36 +136,97 @@ def testModulated(self): self.assertTrue(energy_ratio < 0.10) - def testEvaluateExpand(self): - coef1 = randn(self.basis.count, seed=self.seed) - coef1 = coef1.astype(self.dtype) - im = self.basis.evaluate(coef1) - if isinstance(im, Image): - im = im.asnumpy() - coef2 = self.basis.expand(im)[0] +class Steerable3DMixin(SteerableMixin): + def testIndices(self): + ell_max = self.basis.ell_max + k_max = self.basis.k_max - self.assertTrue(coef1.shape == coef2.shape) - self.assertTrue(np.allclose(coef1, coef2, atol=utest_tolerance(self.dtype))) + indices = self.basis.indices() - def testAdjoint(self): - u = randn(self.basis.count, seed=self.seed) - u = u.astype(self.dtype) + i = 0 - Au = self.basis.evaluate(u) - if isinstance(Au, Image): - Au = Au.asnumpy() + for ell in range(ell_max + 1): + for m in range(-ell, ell + 1): + for k in range(k_max[ell]): + self.assertTrue(indices["ells"][i] == ell) + self.assertTrue(indices["ms"][i] == m) + self.assertTrue(indices["ks"][i] == k) - x = randn(*self.basis.sz, seed=self.seed) - x = x.astype(self.dtype) + i += 1 - ATx = self.basis.evaluate_t(x) + def testGaussianExpand(self): + # Offset slightly + x0 = 0.50 + y0 = 0.75 + z0 = 0.25 - Au_dot_x = np.sum(Au * x) - u_dot_ATx = np.sum(u * ATx) + # Want sigma to be as large as possible without the Gaussian + # spilling too much outside the central disk. + sigma = self.L / 8 + vol1 = gaussian_3d( + self.L, mu=(x0, y0, z0), sigma=(sigma, sigma, sigma), dtype=self.dtype + ) - self.assertTrue(Au_dot_x.shape == u_dot_ATx.shape) - self.assertTrue(np.isclose(Au_dot_x, u_dot_ATx)) + vol1 = vol1[np.newaxis] + + coef = self.basis.expand(vol1) + vol2 = self.basis.evaluate(coef) + + if isinstance(vol2, Volume): + vol2 = vol2.asnumpy() + + # For small L there's too much clipping at high freqs to get 1e-3 + # accuracy. + if self.L < 16: + atol = 1e-1 + elif self.L < 32: + atol = 1e-2 + else: + atol = 1e-3 + + self.assertEqual(vol1.shape, vol2.shape) + self.assertTrue(np.allclose(vol1, vol2, atol=atol)) + + def testIsotropic(self): + sigma = self.L / 8 + im = gaussian_3d(self.L, sigma=(sigma, sigma, sigma), dtype=self.dtype) + + coef = self.basis.expand(im) + + ells = self.basis.indices()["ells"] + + energy_outside = np.sum(np.abs(coef[ells != 0]) ** 2) + energy_total = np.sum(np.abs(coef) ** 2) + + energy_ratio = energy_outside / energy_total + + self.assertTrue(energy_ratio < 0.01) + + def testModulated(self): + if self.L < 32: + raise SkipTest + + ell = 1 + + sigma = self.L / 8 + vol = gaussian_3d(self.L, sigma=(sigma, sigma, sigma), dtype=self.dtype) + + g3d = grid_3d(self.L) + + for trig_fun in (np.sin, np.cos): + vol1 = vol * trig_fun(ell * g3d["phi"]) + + coef = self.basis.expand(vol1) + + ells = self.basis.indices()["ells"] + + energy_outside = np.sum(np.abs(coef[ells != ell]) ** 2) + energy_total = np.sum(np.abs(coef) ** 2) + + energy_ratio = energy_outside / energy_total + + self.assertTrue(energy_ratio < 0.10) class UniversalBasisMixin: diff --git a/tests/test_FBbasis3D.py b/tests/test_FBbasis3D.py index 970c475ab7..2c4f2b9c27 100644 --- a/tests/test_FBbasis3D.py +++ b/tests/test_FBbasis3D.py @@ -2,706 +2,31 @@ from unittest import TestCase import numpy as np +from parameterized import parameterized_class from aspire.basis import FBBasis3D -from aspire.utils import utest_tolerance -from aspire.volume import Volume -from ._basis_util import UniversalBasisMixin +from ._basis_util import Steerable3DMixin, UniversalBasisMixin DATA_DIR = os.path.join(os.path.dirname(__file__), "saved_test_data") -class FBBasis3DTestCase(TestCase, UniversalBasisMixin): +# NOTE: Class with default values is already present, so don't list it below. +@parameterized_class( + ("L", "dtype"), + [ + (8, np.float64), + (16, np.float32), + (16, np.float64), + ], +) +class FBBasis3DTestCase(TestCase, Steerable3DMixin, UniversalBasisMixin): + L = 8 + dtype = np.float32 + def setUp(self): - self.L = 8 - self.dtype = np.float32 self.basis = FBBasis3D((self.L, self.L, self.L), dtype=self.dtype) + self.seed = 9161341 def tearDown(self): pass - - def testFBBasis3DIndices(self): - indices = self.basis.indices() - - self.assertTrue( - np.allclose( - indices["ells"], - [ - 0.0, - 0.0, - 0.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 5.0, - 5.0, - 5.0, - 5.0, - 5.0, - 5.0, - 5.0, - 5.0, - 5.0, - 5.0, - 5.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - ], - ) - ) - - self.assertTrue( - np.allclose( - indices["ms"], - [ - 0.0, - 0.0, - 0.0, - -1.0, - -1.0, - -1.0, - 0.0, - 0.0, - 0.0, - 1.0, - 1.0, - 1.0, - -2.0, - -2.0, - -2.0, - -1.0, - -1.0, - -1.0, - 0.0, - 0.0, - 0.0, - 1.0, - 1.0, - 1.0, - 2.0, - 2.0, - 2.0, - -3.0, - -3.0, - -2.0, - -2.0, - -1.0, - -1.0, - 0.0, - 0.0, - 1.0, - 1.0, - 2.0, - 2.0, - 3.0, - 3.0, - -4.0, - -4.0, - -3.0, - -3.0, - -2.0, - -2.0, - -1.0, - -1.0, - 0.0, - 0.0, - 1.0, - 1.0, - 2.0, - 2.0, - 3.0, - 3.0, - 4.0, - 4.0, - -5.0, - -4.0, - -3.0, - -2.0, - -1.0, - 0.0, - 1.0, - 2.0, - 3.0, - 4.0, - 5.0, - -6.0, - -5.0, - -4.0, - -3.0, - -2.0, - -1.0, - 0.0, - 1.0, - 2.0, - 3.0, - 4.0, - 5.0, - 6.0, - -7.0, - -6.0, - -5.0, - -4.0, - -3.0, - -2.0, - -1.0, - 0.0, - 1.0, - 2.0, - 3.0, - 4.0, - 5.0, - 6.0, - 7.0, - ], - ) - ) - - self.assertTrue( - np.allclose( - indices["ks"], - [ - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0, - ], - ) - ) - - def testFBBasis3DNorms(self): - norms = self.basis.norms() - self.assertTrue( - np.allclose( - norms, - [ - 1.80063263231421, - 0.900316316157109, - 0.600210877438065, - 1.22885897287928, - 0.726196138639673, - 0.516613361675378, - 0.936477951517100, - 0.610605075148750, - 0.454495363516488, - 0.756963071176142, - 0.527618747123993, - 0.635005913075500, - 0.464867421846148, - 0.546574142892508, - 0.479450758110826, - 0.426739123914569, - ], - ) - ) - - def testFBBasis3DEvaluate(self): - coeffs = np.array( - [ - 1.07338590e-01, - 1.23690941e-01, - 6.44482039e-03, - -5.40484306e-02, - -4.85304586e-02, - 1.09852144e-02, - 3.87838396e-02, - 3.43796455e-02, - -6.43284705e-03, - -2.86677145e-02, - -1.42313328e-02, - -2.25684091e-03, - -3.31840727e-02, - -2.59706174e-03, - -5.91919887e-04, - -9.97433028e-03, - 9.19123928e-04, - 1.19891589e-03, - 7.49154982e-03, - 6.18865229e-03, - -8.13265715e-04, - -1.30715655e-02, - -1.44160603e-02, - 2.90379956e-03, - 2.37066082e-02, - 4.88805735e-03, - 1.47870707e-03, - 7.63376018e-03, - -5.60619559e-03, - 1.05165081e-02, - 3.30510143e-03, - -3.48652120e-03, - -4.23228797e-04, - 1.40484061e-02, - 1.42914291e-03, - -1.28129504e-02, - 2.19868825e-03, - -6.30835037e-03, - 1.18524223e-03, - -2.97855052e-02, - 1.15491057e-03, - -8.27947006e-03, - 3.45442781e-03, - -4.72868856e-03, - 2.66615329e-03, - -7.87929790e-03, - 8.84126590e-04, - 1.59402808e-03, - -9.06854048e-05, - -8.79119004e-03, - 1.76449039e-03, - -1.36414673e-02, - 1.56793855e-03, - 1.44708445e-02, - -2.55974802e-03, - 5.38506357e-03, - -3.24188673e-03, - 4.81582945e-04, - 7.74260101e-05, - 5.48772082e-03, - 1.92058500e-03, - -4.63538896e-03, - -2.02735133e-03, - 3.67592386e-03, - 7.23486969e-04, - 1.81838422e-03, - 1.78793284e-03, - -8.01474060e-03, - -8.54007528e-03, - 1.96353845e-03, - -2.16254252e-03, - -3.64243996e-05, - -2.27329863e-03, - 1.11424393e-03, - -1.39389189e-03, - 2.57787159e-04, - 3.66918811e-03, - 1.31477774e-03, - 6.82220128e-04, - 1.41822851e-03, - -1.89476924e-03, - -6.43966255e-05, - -7.87888465e-04, - -6.99459279e-04, - 1.08918981e-03, - 2.25264584e-03, - -1.43651015e-04, - 7.68377620e-04, - 5.05955256e-04, - 2.66936132e-06, - 2.24934884e-03, - 6.70529439e-04, - 4.81121742e-04, - -6.40789745e-05, - -3.35915672e-04, - -7.98651783e-04, - -9.82705453e-04, - 6.46337066e-05, - ], - dtype=self.dtype, - ) - result = self.basis.evaluate(coeffs) - - self.assertTrue( - np.allclose( - result.asnumpy(), - np.load(os.path.join(DATA_DIR, "hbbasis_evaluation_8_8_8.npy")).T, - atol=utest_tolerance(self.dtype), - ) - ) - - def testFBBasis3DEvaluate_t(self): - v = np.load(os.path.join(DATA_DIR, "hbbasis_coefficients_8_8_8.npy")).T - v = Volume(v.astype(self.dtype)) - result = self.basis.evaluate_t(v) - - self.assertTrue( - np.allclose( - result, - [ - 1.07338590e-01, - 1.23690941e-01, - 6.44482039e-03, - -5.40484306e-02, - -4.85304586e-02, - 1.09852144e-02, - 3.87838396e-02, - 3.43796455e-02, - -6.43284705e-03, - -2.86677145e-02, - -1.42313328e-02, - -2.25684091e-03, - -3.31840727e-02, - -2.59706174e-03, - -5.91919887e-04, - -9.97433028e-03, - 9.19123928e-04, - 1.19891589e-03, - 7.49154982e-03, - 6.18865229e-03, - -8.13265715e-04, - -1.30715655e-02, - -1.44160603e-02, - 2.90379956e-03, - 2.37066082e-02, - 4.88805735e-03, - 1.47870707e-03, - 7.63376018e-03, - -5.60619559e-03, - 1.05165081e-02, - 3.30510143e-03, - -3.48652120e-03, - -4.23228797e-04, - 1.40484061e-02, - 1.42914291e-03, - -1.28129504e-02, - 2.19868825e-03, - -6.30835037e-03, - 1.18524223e-03, - -2.97855052e-02, - 1.15491057e-03, - -8.27947006e-03, - 3.45442781e-03, - -4.72868856e-03, - 2.66615329e-03, - -7.87929790e-03, - 8.84126590e-04, - 1.59402808e-03, - -9.06854048e-05, - -8.79119004e-03, - 1.76449039e-03, - -1.36414673e-02, - 1.56793855e-03, - 1.44708445e-02, - -2.55974802e-03, - 5.38506357e-03, - -3.24188673e-03, - 4.81582945e-04, - 7.74260101e-05, - 5.48772082e-03, - 1.92058500e-03, - -4.63538896e-03, - -2.02735133e-03, - 3.67592386e-03, - 7.23486969e-04, - 1.81838422e-03, - 1.78793284e-03, - -8.01474060e-03, - -8.54007528e-03, - 1.96353845e-03, - -2.16254252e-03, - -3.64243996e-05, - -2.27329863e-03, - 1.11424393e-03, - -1.39389189e-03, - 2.57787159e-04, - 3.66918811e-03, - 1.31477774e-03, - 6.82220128e-04, - 1.41822851e-03, - -1.89476924e-03, - -6.43966255e-05, - -7.87888465e-04, - -6.99459279e-04, - 1.08918981e-03, - 2.25264584e-03, - -1.43651015e-04, - 7.68377620e-04, - 5.05955256e-04, - 2.66936132e-06, - 2.24934884e-03, - 6.70529439e-04, - 4.81121742e-04, - -6.40789745e-05, - -3.35915672e-04, - -7.98651783e-04, - -9.82705453e-04, - 6.46337066e-05, - ], - atol=utest_tolerance(self.dtype), - ) - ) - - def testFBBasis3DExpand(self): - v = np.load(os.path.join(DATA_DIR, "hbbasis_coefficients_8_8_8.npy")).T - v = Volume(v.astype(self.dtype)) - result = self.basis.expand(v) - - self.assertTrue( - np.allclose( - result, - [ - +0.10743660, - +0.12346847, - +0.00684837, - -0.05410818, - -0.04840195, - +0.01071116, - +0.03878536, - +0.03437083, - -0.00638332, - -0.02865552, - -0.01425294, - -0.00223313, - -0.03317134, - -0.00261654, - -0.00056954, - -0.00997264, - +0.00091569, - +0.00123042, - +0.00754713, - +0.00606669, - -0.00043233, - -0.01306626, - -0.01443522, - +0.00301968, - +0.02375521, - +0.00477979, - +0.00166319, - +0.00780333, - -0.00601982, - +0.01052385, - +0.00328666, - -0.00336805, - -0.00070688, - +0.01409127, - +0.00127259, - -0.01289172, - +0.00234488, - -0.00630249, - +0.00117541, - -0.02974037, - +0.00108834, - -0.00823955, - +0.00340772, - -0.00471875, - +0.00266391, - -0.00789639, - +0.00093529, - +0.00160710, - -0.00011925, - -0.00817443, - +0.00046713, - -0.01357463, - +0.00145920, - +0.01452459, - -0.00267202, - +0.00535952, - -0.00322100, - +0.00092083, - -0.00075300, - +0.00509418, - +0.00193687, - -0.00483399, - -0.00204537, - +0.00338492, - +0.00111248, - +0.00194841, - +0.00174416, - -0.00814324, - -0.00839777, - +0.00199974, - -0.00196156, - -0.00014695, - -0.00245317, - +0.00109957, - -0.00146145, - +0.00015149, - +0.00415232, - +0.00121810, - +0.00066095, - +0.00166167, - -0.00231911, - -0.00025819, - -0.00086808, - -0.00074656, - +0.00110445, - +0.00285573, - -0.00014959, - +0.00093241, - +0.00051144, - +0.00004805, - +0.00250166, - +0.00059104, - +0.00066592, - +0.00019188, - -0.00079074, - -0.00068995, - -0.00087668, - +0.00052913, - ], - atol=utest_tolerance(self.dtype), - ) - ) diff --git a/tests/test_FFBbasis3D.py b/tests/test_FFBbasis3D.py index c07c14dee7..8ae9c70eae 100644 --- a/tests/test_FFBbasis3D.py +++ b/tests/test_FFBbasis3D.py @@ -2,496 +2,33 @@ from unittest import TestCase import numpy as np +from parameterized import parameterized_class from aspire.basis import FFBBasis3D -from ._basis_util import UniversalBasisMixin +from ._basis_util import Steerable3DMixin, UniversalBasisMixin DATA_DIR = os.path.join(os.path.dirname(__file__), "saved_test_data") -class FFBBasis3DTestCase(TestCase, UniversalBasisMixin): +# NOTE: Class with default values is already present, so don't list it below. +@parameterized_class( + ("L", "dtype"), + [ + (8, np.float64), + (16, np.float32), + (16, np.float64), + (32, np.float32), + (32, np.float64), + ], +) +class FFBBasis3DTestCase(TestCase, Steerable3DMixin, UniversalBasisMixin): + L = 8 + dtype = np.float32 + def setUp(self): - self.L = 8 - self.dtype = np.float32 self.basis = FFBBasis3D((self.L, self.L, self.L), dtype=self.dtype) + self.seed = 9161341 def tearDown(self): pass - - def testFFBBasis3DIndices(self): - indices = self.basis.indices() - - self.assertTrue( - np.allclose( - indices["ells"], - [ - 0.0, - 0.0, - 0.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 2.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 3.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 4.0, - 5.0, - 5.0, - 5.0, - 5.0, - 5.0, - 5.0, - 5.0, - 5.0, - 5.0, - 5.0, - 5.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 6.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - 7.0, - ], - ) - ) - - self.assertTrue( - np.allclose( - indices["ms"], - [ - 0.0, - 0.0, - 0.0, - -1.0, - -1.0, - -1.0, - 0.0, - 0.0, - 0.0, - 1.0, - 1.0, - 1.0, - -2.0, - -2.0, - -2.0, - -1.0, - -1.0, - -1.0, - 0.0, - 0.0, - 0.0, - 1.0, - 1.0, - 1.0, - 2.0, - 2.0, - 2.0, - -3.0, - -3.0, - -2.0, - -2.0, - -1.0, - -1.0, - 0.0, - 0.0, - 1.0, - 1.0, - 2.0, - 2.0, - 3.0, - 3.0, - -4.0, - -4.0, - -3.0, - -3.0, - -2.0, - -2.0, - -1.0, - -1.0, - 0.0, - 0.0, - 1.0, - 1.0, - 2.0, - 2.0, - 3.0, - 3.0, - 4.0, - 4.0, - -5.0, - -4.0, - -3.0, - -2.0, - -1.0, - 0.0, - 1.0, - 2.0, - 3.0, - 4.0, - 5.0, - -6.0, - -5.0, - -4.0, - -3.0, - -2.0, - -1.0, - 0.0, - 1.0, - 2.0, - 3.0, - 4.0, - 5.0, - 6.0, - -7.0, - -6.0, - -5.0, - -4.0, - -3.0, - -2.0, - -1.0, - 0.0, - 1.0, - 2.0, - 3.0, - 4.0, - 5.0, - 6.0, - 7.0, - ], - ) - ) - - self.assertTrue( - np.allclose( - indices["ks"], - [ - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 2.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 1.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0, - ], - ) - ) - - def testFFBBasis3DNorms(self): - norms = self.basis.norms() - self.assertTrue( - np.allclose( - norms, - [ - 1.80063263231421, - 0.900316316157109, - 0.600210877438065, - 1.22885897287928, - 0.726196138639673, - 0.516613361675378, - 0.936477951517100, - 0.610605075148750, - 0.454495363516488, - 0.756963071176142, - 0.527618747123993, - 0.635005913075500, - 0.464867421846148, - 0.546574142892508, - 0.479450758110826, - 0.426739123914569, - ], - ) - ) - - def testFFBBasis3DEvaluate(self): - coeffs = np.array( - [ - 1.07338590e-01, - 1.23690941e-01, - 6.44482039e-03, - -5.40484306e-02, - -4.85304586e-02, - 1.09852144e-02, - 3.87838396e-02, - 3.43796455e-02, - -6.43284705e-03, - -2.86677145e-02, - -1.42313328e-02, - -2.25684091e-03, - -3.31840727e-02, - -2.59706174e-03, - -5.91919887e-04, - -9.97433028e-03, - 9.19123928e-04, - 1.19891589e-03, - 7.49154982e-03, - 6.18865229e-03, - -8.13265715e-04, - -1.30715655e-02, - -1.44160603e-02, - 2.90379956e-03, - 2.37066082e-02, - 4.88805735e-03, - 1.47870707e-03, - 7.63376018e-03, - -5.60619559e-03, - 1.05165081e-02, - 3.30510143e-03, - -3.48652120e-03, - -4.23228797e-04, - 1.40484061e-02, - 1.42914291e-03, - -1.28129504e-02, - 2.19868825e-03, - -6.30835037e-03, - 1.18524223e-03, - -2.97855052e-02, - 1.15491057e-03, - -8.27947006e-03, - 3.45442781e-03, - -4.72868856e-03, - 2.66615329e-03, - -7.87929790e-03, - 8.84126590e-04, - 1.59402808e-03, - -9.06854048e-05, - -8.79119004e-03, - 1.76449039e-03, - -1.36414673e-02, - 1.56793855e-03, - 1.44708445e-02, - -2.55974802e-03, - 5.38506357e-03, - -3.24188673e-03, - 4.81582945e-04, - 7.74260101e-05, - 5.48772082e-03, - 1.92058500e-03, - -4.63538896e-03, - -2.02735133e-03, - 3.67592386e-03, - 7.23486969e-04, - 1.81838422e-03, - 1.78793284e-03, - -8.01474060e-03, - -8.54007528e-03, - 1.96353845e-03, - -2.16254252e-03, - -3.64243996e-05, - -2.27329863e-03, - 1.11424393e-03, - -1.39389189e-03, - 2.57787159e-04, - 3.66918811e-03, - 1.31477774e-03, - 6.82220128e-04, - 1.41822851e-03, - -1.89476924e-03, - -6.43966255e-05, - -7.87888465e-04, - -6.99459279e-04, - 1.08918981e-03, - 2.25264584e-03, - -1.43651015e-04, - 7.68377620e-04, - 5.05955256e-04, - 2.66936132e-06, - 2.24934884e-03, - 6.70529439e-04, - 4.81121742e-04, - -6.40789745e-05, - -3.35915672e-04, - -7.98651783e-04, - -9.82705453e-04, - 6.46337066e-05, - ], - dtype=self.dtype, - ) - result = self.basis.evaluate(coeffs) - - ref = np.load( - os.path.join(DATA_DIR, "ffbbasis3d_xcoeff_out_8_8_8.npy") - ).T # RCOPT - - self.assertTrue(np.allclose(result, ref, atol=1e-2)) - - def testFFBBasis3DEvaluate_t(self): - x = np.load(os.path.join(DATA_DIR, "ffbbasis3d_xcoeff_in_8_8_8.npy")).T # RCOPT - result = self.basis.evaluate_t(x) - - ref = np.load(os.path.join(DATA_DIR, "ffbbasis3d_vcoeff_out_8_8_8.npy"))[..., 0] - - self.assertTrue(np.allclose(result, ref, atol=1e-2)) - - def testFFBBasis3DExpand(self): - x = np.load(os.path.join(DATA_DIR, "ffbbasis3d_xcoeff_in_8_8_8.npy")).T # RCOPT - result = self.basis.expand(x) - - ref = np.load(os.path.join(DATA_DIR, "ffbbasis3d_vcoeff_out_exp_8_8_8.npy"))[ - ..., 0 - ] - - self.assertTrue(np.allclose(result, ref, atol=1e-2))