From d3cda4677438f3cd63d9caafd811270118467d31 Mon Sep 17 00:00:00 2001 From: Junchao Xia Date: Fri, 6 Nov 2020 17:27:24 -0500 Subject: [PATCH 1/8] Remove unneccessary dtype --- src/aspire/denoising/denoiser_cov2d.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aspire/denoising/denoiser_cov2d.py b/src/aspire/denoising/denoiser_cov2d.py index efa2769fd0..f2c8becbd0 100644 --- a/src/aspire/denoising/denoiser_cov2d.py +++ b/src/aspire/denoising/denoiser_cov2d.py @@ -43,7 +43,7 @@ def denoise(self, covar_opt=None, batch_size=512): # Initialize the rotationally invariant covariance matrix of 2D images # A fixed batch size is used to go through each image self.cov2d = BatchedRotCov2D( - self.src, self.basis, batch_size=batch_size, dtype=self.dtype + self.src, self.basis, batch_size=batch_size ) default_opt = { From aa4aea7dd02143a478578cb5a9f7f41ad52c9724 Mon Sep 17 00:00:00 2001 From: Junchao Xia Date: Fri, 6 Nov 2020 17:28:36 -0500 Subject: [PATCH 2/8] Add unit tests for cov2d Denoisor --- tests/test_covar2d_denoiser.py | 83 ++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 tests/test_covar2d_denoiser.py diff --git a/tests/test_covar2d_denoiser.py b/tests/test_covar2d_denoiser.py new file mode 100644 index 0000000000..ae6cdff442 --- /dev/null +++ b/tests/test_covar2d_denoiser.py @@ -0,0 +1,83 @@ +from unittest import TestCase + +import numpy as np + +from aspire.basis.ffb_2d import FFBBasis2D +from aspire.estimation.covar2d import BatchedRotCov2D +from aspire.denoising.denoiser_cov2d import DenoiserCov2D +from aspire.source.simulation import Simulation +from aspire.utils.filters import RadialCTFFilter, ScalarFilter + + +class BatchedRotCov2DTestCase(TestCase): + def setUp(self): + n = 32 + L = 8 + self.dtype = np.float32 + + self.noise_var = 0.1848 + noise_filter = ScalarFilter(dim=2, value=self.noise_var) + + pixel_size = 5 + voltage = 200 + defocus_min = 1.5e4 + defocus_max = 2.5e4 + defocus_ct = 7 + + filters = [RadialCTFFilter(pixel_size, voltage, defocus=d, Cs=2.0, alpha=0.1) + for d in np.linspace(defocus_min, defocus_max, defocus_ct)] + + src = Simulation(L, n, unique_filters=filters, dtype=self.dtype, + noise_filter=noise_filter) + + basis = FFBBasis2D((L, L), dtype=self.dtype) + + unique_filters = src.unique_filters + self.ctf_idx = src.filter_indices + self.ctf_fb = [f.fb_mat(basis) for f in unique_filters] + + im = src.images(0, src.n) + self.coeff = basis.evaluate_t(im) + + self.bcov2d = BatchedRotCov2D(src, basis, batch_size=7) + self.denoisor = DenoiserCov2D(src, basis, self.noise_var) + self.denoised_src = self.denoisor.denoise(batch_size=7) + self.src = src + self.basis = basis + self.covar_est_opt = {'shrinker': 'frobenius_norm', 'verbose': 0, + 'max_iter': 250, 'iter_callback': [], + 'store_iterates': False, 'rel_tolerance': 1e-12, + 'precision': self.dtype} + + def blk_diag_allclose(self, blk_diag_a, blk_diag_b, atol=1e-8): + close = True + for blk_a, blk_b in zip(blk_diag_a, blk_diag_b): + close = (close and np.allclose(blk_a, blk_b, atol=atol)) + return close + + def testMean(self): + mean_bcov2d = self.bcov2d.get_mean() + mean_denoisor = self.denoisor.mean_est + + self.assertTrue(np.allclose(mean_denoisor, mean_bcov2d)) + + def testCovar(self): + covar_bcov2d = self.bcov2d.get_covar(noise_var=self.noise_var, + covar_est_opt=self.covar_est_opt) + covar_denoisor = self.denoisor.covar_est + + self.assertTrue(self.blk_diag_allclose(covar_denoisor, covar_bcov2d)) + + def testCWFCeoffs(self): + mean_bcov2d = self.bcov2d.get_mean() + covar_bcov2d = self.bcov2d.get_covar(noise_var=self.noise_var, + covar_est_opt=self.covar_est_opt) + coeffs_bcov2d = self.bcov2d.get_cwf_coeffs( + self.coeff, self.ctf_fb, self.ctf_idx, + mean_coeff=mean_bcov2d, covar_coeff=covar_bcov2d, + noise_var=self.noise_var) + imgs_denoised_bcov2d = self.basis.evaluate(coeffs_bcov2d) + imgs_denoised_denoisor = self.denoised_src.images(0, self.src.n) + + self.assertTrue(np.allclose(imgs_denoised_bcov2d.asnumpy(), + imgs_denoised_denoisor.asnumpy())) From fbf04d5faa7512947e93a64433b466ca3a89c859 Mon Sep 17 00:00:00 2001 From: Junchao Xia Date: Thu, 12 Nov 2020 14:29:24 -0500 Subject: [PATCH 3/8] Run commands to improve format --- src/aspire/denoising/denoiser_cov2d.py | 4 +- tests/test_covar2d_denoiser.py | 55 +++++++++++++++++--------- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/aspire/denoising/denoiser_cov2d.py b/src/aspire/denoising/denoiser_cov2d.py index f2c8becbd0..a4371ba6a5 100644 --- a/src/aspire/denoising/denoiser_cov2d.py +++ b/src/aspire/denoising/denoiser_cov2d.py @@ -42,9 +42,7 @@ def denoise(self, covar_opt=None, batch_size=512): # Initialize the rotationally invariant covariance matrix of 2D images # A fixed batch size is used to go through each image - self.cov2d = BatchedRotCov2D( - self.src, self.basis, batch_size=batch_size - ) + self.cov2d = BatchedRotCov2D(self.src, self.basis, batch_size=batch_size) default_opt = { "shrinker": "frobenius_norm", diff --git a/tests/test_covar2d_denoiser.py b/tests/test_covar2d_denoiser.py index ae6cdff442..6ddcfecd08 100644 --- a/tests/test_covar2d_denoiser.py +++ b/tests/test_covar2d_denoiser.py @@ -3,8 +3,8 @@ import numpy as np from aspire.basis.ffb_2d import FFBBasis2D -from aspire.estimation.covar2d import BatchedRotCov2D from aspire.denoising.denoiser_cov2d import DenoiserCov2D +from aspire.estimation.covar2d import BatchedRotCov2D from aspire.source.simulation import Simulation from aspire.utils.filters import RadialCTFFilter, ScalarFilter @@ -24,11 +24,14 @@ def setUp(self): defocus_max = 2.5e4 defocus_ct = 7 - filters = [RadialCTFFilter(pixel_size, voltage, defocus=d, Cs=2.0, alpha=0.1) - for d in np.linspace(defocus_min, defocus_max, defocus_ct)] + filters = [ + RadialCTFFilter(pixel_size, voltage, defocus=d, Cs=2.0, alpha=0.1) + for d in np.linspace(defocus_min, defocus_max, defocus_ct) + ] - src = Simulation(L, n, unique_filters=filters, dtype=self.dtype, - noise_filter=noise_filter) + src = Simulation( + L, n, unique_filters=filters, dtype=self.dtype, noise_filter=noise_filter + ) basis = FFBBasis2D((L, L), dtype=self.dtype) @@ -44,15 +47,20 @@ def setUp(self): self.denoised_src = self.denoisor.denoise(batch_size=7) self.src = src self.basis = basis - self.covar_est_opt = {'shrinker': 'frobenius_norm', 'verbose': 0, - 'max_iter': 250, 'iter_callback': [], - 'store_iterates': False, 'rel_tolerance': 1e-12, - 'precision': self.dtype} + self.covar_est_opt = { + "shrinker": "frobenius_norm", + "verbose": 0, + "max_iter": 250, + "iter_callback": [], + "store_iterates": False, + "rel_tolerance": 1e-12, + "precision": self.dtype, + } def blk_diag_allclose(self, blk_diag_a, blk_diag_b, atol=1e-8): close = True for blk_a, blk_b in zip(blk_diag_a, blk_diag_b): - close = (close and np.allclose(blk_a, blk_b, atol=atol)) + close = close and np.allclose(blk_a, blk_b, atol=atol) return close def testMean(self): @@ -62,22 +70,31 @@ def testMean(self): self.assertTrue(np.allclose(mean_denoisor, mean_bcov2d)) def testCovar(self): - covar_bcov2d = self.bcov2d.get_covar(noise_var=self.noise_var, - covar_est_opt=self.covar_est_opt) + covar_bcov2d = self.bcov2d.get_covar( + noise_var=self.noise_var, covar_est_opt=self.covar_est_opt + ) covar_denoisor = self.denoisor.covar_est self.assertTrue(self.blk_diag_allclose(covar_denoisor, covar_bcov2d)) def testCWFCeoffs(self): mean_bcov2d = self.bcov2d.get_mean() - covar_bcov2d = self.bcov2d.get_covar(noise_var=self.noise_var, - covar_est_opt=self.covar_est_opt) + covar_bcov2d = self.bcov2d.get_covar( + noise_var=self.noise_var, covar_est_opt=self.covar_est_opt + ) coeffs_bcov2d = self.bcov2d.get_cwf_coeffs( - self.coeff, self.ctf_fb, self.ctf_idx, - mean_coeff=mean_bcov2d, covar_coeff=covar_bcov2d, - noise_var=self.noise_var) + self.coeff, + self.ctf_fb, + self.ctf_idx, + mean_coeff=mean_bcov2d, + covar_coeff=covar_bcov2d, + noise_var=self.noise_var, + ) imgs_denoised_bcov2d = self.basis.evaluate(coeffs_bcov2d) imgs_denoised_denoisor = self.denoised_src.images(0, self.src.n) - self.assertTrue(np.allclose(imgs_denoised_bcov2d.asnumpy(), - imgs_denoised_denoisor.asnumpy())) + self.assertTrue( + np.allclose( + imgs_denoised_bcov2d.asnumpy(), imgs_denoised_denoisor.asnumpy() + ) + ) From 6244f0cbe0cddcfaf291cfe006c19bb709b61737 Mon Sep 17 00:00:00 2001 From: Junchao Xia Date: Fri, 13 Nov 2020 18:07:28 -0500 Subject: [PATCH 4/8] Change column major to row major and fix bug --- src/aspire/denoising/denoised_src.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/aspire/denoising/denoised_src.py b/src/aspire/denoising/denoised_src.py index df6a6d956f..7ec454cade 100644 --- a/src/aspire/denoising/denoised_src.py +++ b/src/aspire/denoising/denoised_src.py @@ -40,11 +40,13 @@ def _images(self, start=0, num=np.inf, indices=None, batch_size=512): start = indices.min() end = indices.max() - im = np.empty((self.L, self.L, len(indices))) + nimgs = len(indices) + im = np.empty((nimgs, self.L, self.L)) - logger.info(f"Loading {len(indices)} images complete") - for istart in range(start, end, batch_size): + logger.info(f"Loading {nimgs} images complete") + for istart in range(start, end + 1, batch_size): imgs_denoised = self.denoiser.images(istart, batch_size) - im = imgs_denoised.data + iend = min(istart + batch_size, end + 1) + im[istart:iend] = imgs_denoised.data return Image(im) From dfade246e1fe4c2ca1990dc3df1ff0f72bbc8a2c Mon Sep 17 00:00:00 2001 From: Junchao Xia Date: Fri, 13 Nov 2020 18:08:01 -0500 Subject: [PATCH 5/8] Add unit test for MSE and reduce number of lines --- tests/test_covar2d_denoiser.py | 76 ++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 26 deletions(-) diff --git a/tests/test_covar2d_denoiser.py b/tests/test_covar2d_denoiser.py index 6ddcfecd08..170295c9b4 100644 --- a/tests/test_covar2d_denoiser.py +++ b/tests/test_covar2d_denoiser.py @@ -13,40 +13,31 @@ class BatchedRotCov2DTestCase(TestCase): def setUp(self): n = 32 L = 8 - self.dtype = np.float32 - - self.noise_var = 0.1848 - noise_filter = ScalarFilter(dim=2, value=self.noise_var) - - pixel_size = 5 - voltage = 200 - defocus_min = 1.5e4 - defocus_max = 2.5e4 - defocus_ct = 7 + dtype = np.float32 + noise_var = 0.1848 + noise_filter = ScalarFilter(dim=2, value=noise_var) filters = [ - RadialCTFFilter(pixel_size, voltage, defocus=d, Cs=2.0, alpha=0.1) - for d in np.linspace(defocus_min, defocus_max, defocus_ct) + RadialCTFFilter(5, 200, defocus=d, Cs=2.0, alpha=0.1) + for d in np.linspace(1.5e4, 2.5e4, 7) ] src = Simulation( - L, n, unique_filters=filters, dtype=self.dtype, noise_filter=noise_filter + L, n, unique_filters=filters, dtype=dtype, noise_filter=noise_filter ) - - basis = FFBBasis2D((L, L), dtype=self.dtype) - - unique_filters = src.unique_filters - self.ctf_idx = src.filter_indices - self.ctf_fb = [f.fb_mat(basis) for f in unique_filters] - im = src.images(0, src.n) - self.coeff = basis.evaluate_t(im) - self.bcov2d = BatchedRotCov2D(src, basis, batch_size=7) - self.denoisor = DenoiserCov2D(src, basis, self.noise_var) + self.dtype = dtype + self.basis = FFBBasis2D((L, L), dtype=self.dtype) + self.noise_var = noise_var + self.noise_filter = noise_filter + self.ctf_idx = src.filter_indices + self.ctf_fb = [f.fb_mat(self.basis) for f in src.unique_filters] + self.coeff = self.basis.evaluate_t(im) + self.bcov2d = BatchedRotCov2D(src, self.basis, batch_size=7) + self.denoisor = DenoiserCov2D(src, self.basis, self.noise_var) self.denoised_src = self.denoisor.denoise(batch_size=7) - self.src = src - self.basis = basis + self.covar_est_opt = { "shrinker": "frobenius_norm", "verbose": 0, @@ -91,10 +82,43 @@ def testCWFCeoffs(self): noise_var=self.noise_var, ) imgs_denoised_bcov2d = self.basis.evaluate(coeffs_bcov2d) - imgs_denoised_denoisor = self.denoised_src.images(0, self.src.n) + imgs_denoised_denoisor = self.denoised_src.images(0, self.denoised_src.n) self.assertTrue( np.allclose( imgs_denoised_bcov2d.asnumpy(), imgs_denoised_denoisor.asnumpy() ) ) + + def testMSE(self): + # need larger numbers of images and higher resolution for good MSE + img_size = 64 + num_imgs = 1024 + + # Create filters + ctf_filters = [ + RadialCTFFilter(5, 200, defocus=d, Cs=2.0, alpha=0.1) + for d in np.linspace(1.5e4, 2.5e4, 7) + ] + + # set simulation object + sim = Simulation( + L=img_size, + n=num_imgs, + unique_filters=ctf_filters, + offsets=0.0, + amplitudes=1.0, + dtype=self.dtype, + noise_filter=self.noise_filter, + ) + imgs_clean = sim.projections() + + # Specify the fast FB basis method for expending the 2D images + ffbbasis = FFBBasis2D((img_size, img_size), dtype=self.dtype) + denoisor = DenoiserCov2D(sim, ffbbasis, self.noise_var) + denoised_src = denoisor.denoise(batch_size=64) + imgs_denoised = denoised_src.images(0, num_imgs) + # Calculate the normalized RMSE of the estimated images. + nrmse_ims = (imgs_denoised - imgs_clean).norm() / imgs_clean.norm() + + self.assertTrue(nrmse_ims < 0.25) From ed303d38a32b9739edd3d49eaa3d4ea0c3686ab2 Mon Sep 17 00:00:00 2001 From: Junchao Xia Date: Mon, 23 Nov 2020 16:37:16 -0500 Subject: [PATCH 6/8] Remove repeated ctf filters --- tests/test_covar2d_denoiser.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/test_covar2d_denoiser.py b/tests/test_covar2d_denoiser.py index 170295c9b4..fc93ca30a5 100644 --- a/tests/test_covar2d_denoiser.py +++ b/tests/test_covar2d_denoiser.py @@ -31,6 +31,7 @@ def setUp(self): self.basis = FFBBasis2D((L, L), dtype=self.dtype) self.noise_var = noise_var self.noise_filter = noise_filter + self.filters = filters self.ctf_idx = src.filter_indices self.ctf_fb = [f.fb_mat(self.basis) for f in src.unique_filters] self.coeff = self.basis.evaluate_t(im) @@ -95,17 +96,11 @@ def testMSE(self): img_size = 64 num_imgs = 1024 - # Create filters - ctf_filters = [ - RadialCTFFilter(5, 200, defocus=d, Cs=2.0, alpha=0.1) - for d in np.linspace(1.5e4, 2.5e4, 7) - ] - # set simulation object sim = Simulation( L=img_size, n=num_imgs, - unique_filters=ctf_filters, + unique_filters=self.filters, offsets=0.0, amplitudes=1.0, dtype=self.dtype, From 041bf6298f82964b121d2c7c3ea33498d59fe5ae Mon Sep 17 00:00:00 2001 From: Junchao Xia Date: Tue, 24 Nov 2020 10:43:01 -0500 Subject: [PATCH 7/8] Fix conflict with develop branch --- tests/test_covar2d_denoiser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_covar2d_denoiser.py b/tests/test_covar2d_denoiser.py index fc93ca30a5..3d62393086 100644 --- a/tests/test_covar2d_denoiser.py +++ b/tests/test_covar2d_denoiser.py @@ -4,9 +4,9 @@ from aspire.basis.ffb_2d import FFBBasis2D from aspire.denoising.denoiser_cov2d import DenoiserCov2D -from aspire.estimation.covar2d import BatchedRotCov2D +from aspire.covariance.covar2d import BatchedRotCov2D from aspire.source.simulation import Simulation -from aspire.utils.filters import RadialCTFFilter, ScalarFilter +from aspire.operators.filters import RadialCTFFilter, ScalarFilter class BatchedRotCov2DTestCase(TestCase): From 2c68610d0e1f3b39b6a60453b7df5626ff6ed497 Mon Sep 17 00:00:00 2001 From: Junchao Xia Date: Tue, 24 Nov 2020 11:01:06 -0500 Subject: [PATCH 8/8] Remove all tests except MSE --- tests/test_covar2d_denoiser.py | 98 ++++------------------------------ 1 file changed, 11 insertions(+), 87 deletions(-) diff --git a/tests/test_covar2d_denoiser.py b/tests/test_covar2d_denoiser.py index 3d62393086..7386ef7a4f 100644 --- a/tests/test_covar2d_denoiser.py +++ b/tests/test_covar2d_denoiser.py @@ -4,114 +4,38 @@ from aspire.basis.ffb_2d import FFBBasis2D from aspire.denoising.denoiser_cov2d import DenoiserCov2D -from aspire.covariance.covar2d import BatchedRotCov2D -from aspire.source.simulation import Simulation from aspire.operators.filters import RadialCTFFilter, ScalarFilter +from aspire.source.simulation import Simulation class BatchedRotCov2DTestCase(TestCase): - def setUp(self): - n = 32 - L = 8 + def testMSE(self): + # need larger numbers of images and higher resolution for good MSE dtype = np.float32 - + img_size = 64 + num_imgs = 1024 noise_var = 0.1848 noise_filter = ScalarFilter(dim=2, value=noise_var) filters = [ RadialCTFFilter(5, 200, defocus=d, Cs=2.0, alpha=0.1) for d in np.linspace(1.5e4, 2.5e4, 7) ] - - src = Simulation( - L, n, unique_filters=filters, dtype=dtype, noise_filter=noise_filter - ) - im = src.images(0, src.n) - - self.dtype = dtype - self.basis = FFBBasis2D((L, L), dtype=self.dtype) - self.noise_var = noise_var - self.noise_filter = noise_filter - self.filters = filters - self.ctf_idx = src.filter_indices - self.ctf_fb = [f.fb_mat(self.basis) for f in src.unique_filters] - self.coeff = self.basis.evaluate_t(im) - self.bcov2d = BatchedRotCov2D(src, self.basis, batch_size=7) - self.denoisor = DenoiserCov2D(src, self.basis, self.noise_var) - self.denoised_src = self.denoisor.denoise(batch_size=7) - - self.covar_est_opt = { - "shrinker": "frobenius_norm", - "verbose": 0, - "max_iter": 250, - "iter_callback": [], - "store_iterates": False, - "rel_tolerance": 1e-12, - "precision": self.dtype, - } - - def blk_diag_allclose(self, blk_diag_a, blk_diag_b, atol=1e-8): - close = True - for blk_a, blk_b in zip(blk_diag_a, blk_diag_b): - close = close and np.allclose(blk_a, blk_b, atol=atol) - return close - - def testMean(self): - mean_bcov2d = self.bcov2d.get_mean() - mean_denoisor = self.denoisor.mean_est - - self.assertTrue(np.allclose(mean_denoisor, mean_bcov2d)) - - def testCovar(self): - covar_bcov2d = self.bcov2d.get_covar( - noise_var=self.noise_var, covar_est_opt=self.covar_est_opt - ) - covar_denoisor = self.denoisor.covar_est - - self.assertTrue(self.blk_diag_allclose(covar_denoisor, covar_bcov2d)) - - def testCWFCeoffs(self): - mean_bcov2d = self.bcov2d.get_mean() - covar_bcov2d = self.bcov2d.get_covar( - noise_var=self.noise_var, covar_est_opt=self.covar_est_opt - ) - coeffs_bcov2d = self.bcov2d.get_cwf_coeffs( - self.coeff, - self.ctf_fb, - self.ctf_idx, - mean_coeff=mean_bcov2d, - covar_coeff=covar_bcov2d, - noise_var=self.noise_var, - ) - imgs_denoised_bcov2d = self.basis.evaluate(coeffs_bcov2d) - imgs_denoised_denoisor = self.denoised_src.images(0, self.denoised_src.n) - - self.assertTrue( - np.allclose( - imgs_denoised_bcov2d.asnumpy(), imgs_denoised_denoisor.asnumpy() - ) - ) - - def testMSE(self): - # need larger numbers of images and higher resolution for good MSE - img_size = 64 - num_imgs = 1024 - # set simulation object sim = Simulation( L=img_size, n=num_imgs, - unique_filters=self.filters, + unique_filters=filters, offsets=0.0, amplitudes=1.0, - dtype=self.dtype, - noise_filter=self.noise_filter, + dtype=dtype, + noise_filter=noise_filter, ) imgs_clean = sim.projections() # Specify the fast FB basis method for expending the 2D images - ffbbasis = FFBBasis2D((img_size, img_size), dtype=self.dtype) - denoisor = DenoiserCov2D(sim, ffbbasis, self.noise_var) - denoised_src = denoisor.denoise(batch_size=64) + ffbbasis = FFBBasis2D((img_size, img_size), dtype=dtype) + denoiser = DenoiserCov2D(sim, ffbbasis, noise_var) + denoised_src = denoiser.denoise(batch_size=64) imgs_denoised = denoised_src.images(0, num_imgs) # Calculate the normalized RMSE of the estimated images. nrmse_ims = (imgs_denoised - imgs_clean).norm() / imgs_clean.norm()