From cf24b92bed6cc5e353c73e574adf82e86e41b0b7 Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Thu, 29 Aug 2024 11:01:44 -0400 Subject: [PATCH 01/25] remove scikit radon warning by adjusting radial mask for test image to r < .99 --- tests/test_sinogram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_sinogram.py b/tests/test_sinogram.py index bbf448db97..7a1f32a0e0 100644 --- a/tests/test_sinogram.py +++ b/tests/test_sinogram.py @@ -113,7 +113,7 @@ def test_project_multidim(num_ang): # Generate a mask g = grid_2d(L, normalized=True, shifted=True) - mask = g["r"] < 1 + mask = g["r"] < .99 # Generate images imgs = Image(np.random.random((m, n, L, L))) * mask From fd96cc0a1a2a060233ee8b979066fa62921b2beb Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Thu, 29 Aug 2024 11:36:22 -0400 Subject: [PATCH 02/25] tox --- tests/test_sinogram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_sinogram.py b/tests/test_sinogram.py index 7a1f32a0e0..dc173449b9 100644 --- a/tests/test_sinogram.py +++ b/tests/test_sinogram.py @@ -113,7 +113,7 @@ def test_project_multidim(num_ang): # Generate a mask g = grid_2d(L, normalized=True, shifted=True) - mask = g["r"] < .99 + mask = g["r"] < 0.99 # Generate images imgs = Image(np.random.random((m, n, L, L))) * mask From 2d8b2a23dfb527d83ba80eb13d284bfc92db6506 Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Thu, 29 Aug 2024 15:11:46 -0400 Subject: [PATCH 03/25] resolve scipy cg warning by adjusting version in wrapper to 1.12.0 --- src/aspire/numeric/scipy.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/aspire/numeric/scipy.py b/src/aspire/numeric/scipy.py index 8f2e7d86d8..c913e917a3 100644 --- a/src/aspire/numeric/scipy.py +++ b/src/aspire/numeric/scipy.py @@ -8,10 +8,11 @@ def cg(*args, **kwargs): """ - Supports scipy cg before and after 1.14.0. + Supports scipy cg before and after 1.12.0. """ - # older scipy cg interface uses `tol` instead of `rtol` - if Version(scipy.__version__) < Version("1.14.0"): + # older (<1.12.0) scipy cg interface uses `tol` instead of `rtol`. + # `tol` will be removed in scipy 1.14.0. + if Version(scipy.__version__) < Version("1.12.0"): kwargs["tol"] = kwargs.pop("rtol", None) return scipy.sparse.linalg.cg(*args, **kwargs) From 7886c467c5a74fd99fea525f0372a38fc0e3fec7 Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Thu, 29 Aug 2024 15:23:30 -0400 Subject: [PATCH 04/25] Resolve Matplotlib warning by explicilty closing plots in testing. --- tests/test_simulation.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_simulation.py b/tests/test_simulation.py index 92a29e225e..c90caa5bdd 100644 --- a/tests/test_simulation.py +++ b/tests/test_simulation.py @@ -3,6 +3,7 @@ import tempfile from unittest import TestCase +import matplotlib.pyplot as plt import numpy as np from pytest import raises @@ -38,14 +39,23 @@ def testPixelSize(self): def testImageShow(self): self.sim.images[:].show() + # Explicitly close all figures before making backend changes. + plt.close("all") + @matplotlib_dry_run def testCleanImagesShow(self): self.sim.clean_images[:].show() + # Explicitly close all figures before making backend changes. + plt.close("all") + @matplotlib_dry_run def testProjectionsShow(self): self.sim.projections[:].show() + # Explicitly close all figures before making backend changes. + plt.close("all") + class SimVolTestCase(TestCase): """Test Simulation with Volume provided.""" From ba58b43f9df6c41d505bb951af0b3d5e456ff6cb Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Tue, 3 Sep 2024 10:11:49 -0400 Subject: [PATCH 05/25] explicitly close figures in matplotlib test wrapper. --- tests/test_utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_utils.py b/tests/test_utils.py index ffad5bc9f6..c7617d28a8 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -399,6 +399,9 @@ def matplotlib_no_gui(): yield + # Explicitly close all figures before making backend changes. + matplotlib.pyplot.close("all") + # Restore backend matplotlib.use(backend) From 80274fecd7c1a66d05dfa4181ec55e03a52a7adf Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Tue, 3 Sep 2024 11:10:12 -0400 Subject: [PATCH 06/25] Resolve FRC legend warning by adding default label for single correlation. --- src/aspire/utils/resolution_estimation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aspire/utils/resolution_estimation.py b/src/aspire/utils/resolution_estimation.py index 14c142bdc5..2baefe4491 100644 --- a/src/aspire/utils/resolution_estimation.py +++ b/src/aspire/utils/resolution_estimation.py @@ -354,7 +354,7 @@ def plot(self, cutoff=None, save_to_file=False, labels=None): plt.ylabel("Correlation") plt.ylim([0, 1.1]) for i, line in enumerate(self.correlations): - _label = None + _label = "correlation" if len(self.correlations) > 1: _label = f"{i}" if labels is not None: From 8011e109474f0600f2d6bb077f2e0b9a8cc14f62 Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Tue, 3 Sep 2024 11:16:35 -0400 Subject: [PATCH 07/25] resolve numpy.product warning --- src/aspire/sinogram/sinogram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aspire/sinogram/sinogram.py b/src/aspire/sinogram/sinogram.py index 34451a396d..7c7bb43662 100644 --- a/src/aspire/sinogram/sinogram.py +++ b/src/aspire/sinogram/sinogram.py @@ -42,7 +42,7 @@ def __init__(self, data, dtype=None): self.shape = self._data.shape self.stack_shape = self._data.shape[:-2] self.stack_n_dim = self._data.ndim - 2 - self.n = np.product(self.stack_shape) + self.n = np.prod(self.stack_shape) self.n_angles = self._data.shape[-2] self.n_radial_points = self._data.shape[-1] From 358afa67ee5372323437baa24d28791680e4693a Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Tue, 3 Sep 2024 14:19:03 -0400 Subject: [PATCH 08/25] resolve Conversion of an array wit h ndim > 0 to a scalar is deprecated, by returning scalar for single value returns --- src/aspire/abinitio/commonline_c3_c4.py | 8 +++++++- src/aspire/utils/rotation.py | 4 ++++ tests/test_rotation.py | 3 +++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/aspire/abinitio/commonline_c3_c4.py b/src/aspire/abinitio/commonline_c3_c4.py index 68469618dd..0e0ca76565 100644 --- a/src/aspire/abinitio/commonline_c3_c4.py +++ b/src/aspire/abinitio/commonline_c3_c4.py @@ -850,7 +850,13 @@ def cl_angles_to_ind(cl_angles, n_theta): thetas = np.mod(thetas, 2 * np.pi) # linear scale from [0,2*pi) to [0,n_theta). - return np.mod(np.round(thetas / (2 * np.pi) * n_theta), n_theta).astype(int) + ind = np.mod(np.round(thetas / (2 * np.pi) * n_theta), n_theta).astype(int) + + # Return scalar for single value. + if ind.size == 1: + ind = ind.flat[0] + + return ind @staticmethod def g_sync(rots, order, rots_gt): diff --git a/src/aspire/utils/rotation.py b/src/aspire/utils/rotation.py index 08bec4ca3d..dc713a74ad 100644 --- a/src/aspire/utils/rotation.py +++ b/src/aspire/utils/rotation.py @@ -408,6 +408,10 @@ def angle_dist(r1, r2, dtype=None): theta = (tr_r[non_zero_dist_ind] - 1) / 2 theta = np.maximum(np.minimum(theta, 1), -1) # Clamp theta in [-1,1] dist[non_zero_dist_ind] = np.arccos(theta, dtype=dtype) + + # If we only have one value, return as a scalar. + if dist.size == 1: + dist = dist.flat[0] return dist @staticmethod diff --git a/tests/test_rotation.py b/tests/test_rotation.py index 9e0dba4ec6..e02e650bd5 100644 --- a/tests/test_rotation.py +++ b/tests/test_rotation.py @@ -173,6 +173,9 @@ def test_angle_dist(dtype): with pytest.raises(ValueError, match=r"r1 and r2 are not broadcastable*"): _ = Rotation.angle_dist(rots[:3], rots[:5]) + # Test that single value returns as 0-dim. + assert Rotation.angle_dist(rots[0], rots[1], dtype).ndim == 0 + def test_mean_angular_distance(dtype): rots_z = Rotation.about_axis("z", [0, np.pi / 4, np.pi / 2], dtype=dtype).matrices From dd65d1c0150160e5c6073e0c7d9d09120034f4f8 Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Tue, 3 Sep 2024 16:07:00 -0400 Subject: [PATCH 09/25] Resolve expected BlkDiagMatrix truncation warning. --- tests/test_covar2d_denoiser.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tests/test_covar2d_denoiser.py b/tests/test_covar2d_denoiser.py index 7b4da5511e..c9b749335b 100644 --- a/tests/test_covar2d_denoiser.py +++ b/tests/test_covar2d_denoiser.py @@ -22,8 +22,21 @@ pytest.param(FBBasis2D, marks=pytest.mark.expensive), FFBBasis2D, FLEBasis2D, - pytest.param(PSWFBasis2D, marks=pytest.mark.expensive), - FPSWFBasis2D, + pytest.param( + PSWFBasis2D, + marks=[ + pytest.mark.expensive, + pytest.mark.filterwarnings( + "ignore:BlkDiagMatrix.from_dense truncating values*" + ), + ], + ), + pytest.param( + FPSWFBasis2D, + marks=pytest.mark.filterwarnings( + "ignore:BlkDiagMatrix.from_dense truncating values*" + ), + ), ] From 194434c4facfa6a9d50925c16b468daa9cdf557c Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Wed, 4 Sep 2024 10:04:26 -0400 Subject: [PATCH 10/25] Resolve test_micrograph_source warnings by using zeros instead of empty for test images. --- tests/test_micrograph_source.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_micrograph_source.py b/tests/test_micrograph_source.py index 06c5874a07..d4793cf61f 100644 --- a/tests/test_micrograph_source.py +++ b/tests/test_micrograph_source.py @@ -285,7 +285,7 @@ def test_rectangular_micrograph_source_files(): """ # Test inconsistent mrc files - imgs = [np.empty((7, 7)), np.empty((8, 8))] + imgs = [np.zeros((7, 7)), np.zeros((8, 8))] with tempfile.TemporaryDirectory() as tmp_output_dir: # Save the files for i, img in enumerate(imgs): From 23e3a07b6e99a6a0a7f1f2a244692c13fdbd25f5 Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Mon, 9 Sep 2024 11:04:28 -0400 Subject: [PATCH 11/25] Resolve test_image.py warning. Remove Ray xfail and use context to check caplog. --- tests/test_image.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/test_image.py b/tests/test_image.py index 887e726c0d..ec7bb42e0e 100644 --- a/tests/test_image.py +++ b/tests/test_image.py @@ -353,14 +353,11 @@ def test_asnumpy_readonly(): vw[0, 0, 0] = 123 -@pytest.mark.xfail(reason="Ray logging issue ray#37711", strict=False) def test_corrupt_mrc_load(caplog): """ Test that corrupt mrc files are logged as expected. """ - caplog.set_level(logging.WARNING) - # Create a tmp dir for this test output with tempfile.TemporaryDirectory() as tmpdir_name: # tmp filename @@ -374,13 +371,16 @@ def test_corrupt_mrc_load(caplog): fh.header.map = -1 # Check that we get a WARNING - _ = Image.load(mrc_path) + with caplog.at_level(logging.WARNING): + _ = Image.load(mrc_path) + + # Check the message prefix + assert f"Image.load of {mrc_path} reporting 1 corruptions" in caplog.text - # Check the message prefix - assert f"Image.load of {mrc_path} reporting 1 corruptions" in caplog.text + # Check the message contains the file path + assert mrc_path in caplog.text - # Check the message contains the file path - assert mrc_path in caplog.text + caplog.clear() def test_load_bad_ext(): From bb76e21311695afa6f0082d4385f8a7a6df2ddda Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Mon, 9 Sep 2024 11:42:17 -0400 Subject: [PATCH 12/25] resolve test_FLEbasis2D.py warnings. --- tests/test_FLEbasis2D.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_FLEbasis2D.py b/tests/test_FLEbasis2D.py index ffb1f8f7d1..e60346f84b 100644 --- a/tests/test_FLEbasis2D.py +++ b/tests/test_FLEbasis2D.py @@ -232,7 +232,7 @@ def testRadialConvolution(): # (e.g. CTF) function via FLE coefficients L = 32 - basis = FLEBasis2D(L, match_fb=False) + basis = FLEBasis2D(L, match_fb=False, dtype=np.float64) # load test radial function x = np.load(os.path.join(DATA_DIR, "fle_radial_fn_32x32.npy")).reshape(1, 32, 32) x = x / np.max(np.abs(x.flatten())) @@ -245,7 +245,7 @@ def testRadialConvolution(): imgs_convolved_fle = basis.evaluate(coefs_convolved).asnumpy() # convolve using FFT - x = basis.evaluate(basis.evaluate_t(x)).asnumpy() + x = basis.evaluate(basis.evaluate_t(Image(x))).asnumpy() ims = basis.evaluate(coefs).asnumpy() imgs_convolved_slow = np.zeros((10, L, L)) From 1f292cc767d54b034509cf1cff926df25081a0c0 Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Mon, 9 Sep 2024 12:09:49 -0400 Subject: [PATCH 13/25] resolve numpy multiply overflow warning by using ones for test image instead of np.empty. --- tests/test_image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_image.py b/tests/test_image.py index ec7bb42e0e..89fbde4a84 100644 --- a/tests/test_image.py +++ b/tests/test_image.py @@ -364,7 +364,7 @@ def test_corrupt_mrc_load(caplog): mrc_path = os.path.join(tmpdir_name, "bad.mrc") # Create and save image - Image(np.empty((1, 8, 8), dtype=np.float32)).save(mrc_path) + Image(np.ones((1, 8, 8), dtype=np.float32)).save(mrc_path) # Open mrc file and soft corrupt it with mrcfile.open(mrc_path, "r+") as fh: From 6ef824caccb654ed6b9f3447b0b84477f044e1bd Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Mon, 9 Sep 2024 15:09:38 -0400 Subject: [PATCH 14/25] resolve test_diag_matrix.py invalid cast value warning, by replacing empty's with ones. --- tests/test_diag_matrix.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/test_diag_matrix.py b/tests/test_diag_matrix.py index ecce899105..05805912c9 100644 --- a/tests/test_diag_matrix.py +++ b/tests/test_diag_matrix.py @@ -77,7 +77,7 @@ def test_repr(): Test accessing the `repr` does not crash. """ - d = DiagMatrix(np.empty((10, 8))) + d = DiagMatrix(np.ones((10, 8))) assert repr(d).startswith("DiagMatrix(") @@ -86,7 +86,7 @@ def test_str(): Test accessing the `str` does not crash. """ - d = DiagMatrix(np.empty((10, 8))) + d = DiagMatrix(np.ones((10, 8))) assert str(d).startswith("DiagMatrix(") @@ -104,13 +104,13 @@ def test_len(): """ Test the `len`. """ - d = DiagMatrix(np.empty((10, 8))) + d = DiagMatrix(np.ones((10, 8))) assert d.size == 10 assert d.count == 8 assert len(d) == 10 - d = DiagMatrix(np.empty((2, 5, 8))) + d = DiagMatrix(np.ones((2, 5, 8))) assert d.size == 10 assert d.count == 8 @@ -121,8 +121,8 @@ def test_size_mismatch(): """ Test we raise operating on `DiagMatrix` having different counts. """ - d1 = DiagMatrix(np.empty((10, 8))) - d2 = DiagMatrix(np.empty((10, 7))) + d1 = DiagMatrix(np.ones((10, 8))) + d2 = DiagMatrix(np.ones((10, 7))) with pytest.raises(RuntimeError, match=r".*not same dimension.*"): _ = d1 + d2 @@ -132,8 +132,8 @@ def test_dtype_mismatch(): """ Test we raise operating on `DiagMatrix` having different dtypes. """ - d1 = DiagMatrix(np.empty((10, 8)), dtype=np.float32) - d2 = DiagMatrix(np.empty((10, 8)), dtype=np.float64) + d1 = DiagMatrix(np.ones((10, 8)), dtype=np.float32) + d2 = DiagMatrix(np.ones((10, 8)), dtype=np.float64) with pytest.raises(RuntimeError, match=r".*received different types.*"): _ = d1 + d2 @@ -144,7 +144,7 @@ def test_dtype_passthrough(): Test that the datatype is inferred correctly. """ for dtype in (int, np.float32, np.float64, np.complex64, np.complex128): - d_np = np.empty(42, dtype=dtype) + d_np = np.ones(42, dtype=dtype) d = DiagMatrix(d_np) assert d.dtype == dtype @@ -154,7 +154,7 @@ def test_dtype_cast(): Test that a datatype is cast when overridden. """ for dtype in (int, np.float32, np.float64, np.complex64, np.complex128): - d_np = np.empty(42, dtype=np.float16) + d_np = np.ones(42, dtype=np.float16) d = DiagMatrix(d_np, dtype) assert d.dtype == dtype @@ -444,7 +444,7 @@ def test_diag_badtype_matmul(): """ Test matrix multiply of `DiagMatrix` with incompatible type raises. """ - d1 = DiagMatrix(np.empty(8)) + d1 = DiagMatrix(np.ones(8)) # matmul with pytest.raises(RuntimeError, match=r".*not implemented for.*"): @@ -576,7 +576,7 @@ def test_bad_as_blk_diag(matrix_size, blk_diag): """ with pytest.raises(RuntimeError, match=r".*only implemented for singletons.*"): # Construct via Numpy. - d_np = np.empty((2, matrix_size), dtype=blk_diag.dtype) + d_np = np.ones((2, matrix_size), dtype=blk_diag.dtype) # Create DiagMatrix then convert to BlkDiagMatrix d = DiagMatrix(d_np) @@ -654,7 +654,7 @@ def test_diag_blk_mul(): """ Test mixing `BlkDiagMatrix` with `DiagMatrix` element-wise multiplication raises. """ - d = DiagMatrix(np.empty(8)) + d = DiagMatrix(np.ones(8)) partition = [(4, 4), (4, 4)] b = BlkDiagMatrix.ones(partition, dtype=d.dtype) @@ -672,7 +672,7 @@ def test_non_square_as_blk_diag(): """ Test non square partition blocks raise an error in as_blk_diag. """ - d = DiagMatrix(np.empty(8)) + d = DiagMatrix(np.ones(8)) partition = [(4, 5), (4, 3)] with pytest.raises(RuntimeError, match=r".*not square.*"): @@ -683,8 +683,8 @@ def test_bad_broadcast(): """ Test incompatible stack shapes raise appropriate error. """ - d1 = DiagMatrix(np.empty((2, 3, 8))) - d2 = DiagMatrix(np.empty((2, 2, 8))) + d1 = DiagMatrix(np.ones((2, 3, 8))) + d2 = DiagMatrix(np.ones((2, 2, 8))) with pytest.raises(ValueError, match=r".*incompatible shapes.*"): _ = d1 + d2 From a641921daa3732f3417af79f691da46df2371b54 Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Tue, 10 Sep 2024 09:21:06 -0400 Subject: [PATCH 15/25] catch np.exp overflow warnings --- src/aspire/abinitio/commonline_sync3n.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/aspire/abinitio/commonline_sync3n.py b/src/aspire/abinitio/commonline_sync3n.py index 3c40eb3ac5..6efb429818 100644 --- a/src/aspire/abinitio/commonline_sync3n.py +++ b/src/aspire/abinitio/commonline_sync3n.py @@ -1,5 +1,6 @@ import logging import os.path +import warnings import numpy as np from numpy.linalg import norm @@ -727,7 +728,13 @@ def fun(x, B, P, b, x0, A=A, a=a): # Calculate probabilities ln_f_ind, ln_f_arb = self._pairs_probabilities(Rijs, P**2, A, a, B, b, x0) - Pij = 1 / (1 + (1 - P) / P * np.exp(ln_f_arb - ln_f_ind)) + + with warnings.catch_warnings(): + # For large values of (ln_f_arb - ln_f_ind), numpy exponential will overflow. We still + # get the intended result of Pij = 0, so we capture and ignore the overflow warning. + warnings.filterwarnings("ignore", r".*overflow encountered in exp.*") + + Pij = 1 / (1 + (1 - P) / P * np.exp(ln_f_arb - ln_f_ind)) # Fix singular output num_nan = np.sum(np.isnan(Pij)) From 0f9e9b50f34b2ee2e05fae3e9dfd6c3014591c6e Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Tue, 10 Sep 2024 10:21:43 -0400 Subject: [PATCH 16/25] Add comments explaining changes. --- src/aspire/utils/resolution_estimation.py | 1 + src/aspire/utils/rotation.py | 2 +- tests/test_FLEbasis2D.py | 5 +++-- tests/test_covar2d_denoiser.py | 3 +++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/aspire/utils/resolution_estimation.py b/src/aspire/utils/resolution_estimation.py index 2baefe4491..af5a46f8a9 100644 --- a/src/aspire/utils/resolution_estimation.py +++ b/src/aspire/utils/resolution_estimation.py @@ -354,6 +354,7 @@ def plot(self, cutoff=None, save_to_file=False, labels=None): plt.ylabel("Correlation") plt.ylim([0, 1.1]) for i, line in enumerate(self.correlations): + # Set default label for single correlation (required by plt.legend() below). _label = "correlation" if len(self.correlations) > 1: _label = f"{i}" diff --git a/src/aspire/utils/rotation.py b/src/aspire/utils/rotation.py index dc713a74ad..07a31df9df 100644 --- a/src/aspire/utils/rotation.py +++ b/src/aspire/utils/rotation.py @@ -409,7 +409,7 @@ def angle_dist(r1, r2, dtype=None): theta = np.maximum(np.minimum(theta, 1), -1) # Clamp theta in [-1,1] dist[non_zero_dist_ind] = np.arccos(theta, dtype=dtype) - # If we only have one value, return as a scalar. + # Return scalar for single value. if dist.size == 1: dist = dist.flat[0] return dist diff --git a/tests/test_FLEbasis2D.py b/tests/test_FLEbasis2D.py index e60346f84b..0873d61bab 100644 --- a/tests/test_FLEbasis2D.py +++ b/tests/test_FLEbasis2D.py @@ -230,16 +230,17 @@ def testLowPass(): def testRadialConvolution(): # test ability to accurately convolve with a radial # (e.g. CTF) function via FLE coefficients - L = 32 - basis = FLEBasis2D(L, match_fb=False, dtype=np.float64) + # load test radial function x = np.load(os.path.join(DATA_DIR, "fle_radial_fn_32x32.npy")).reshape(1, 32, 32) x = x / np.max(np.abs(x.flatten())) # get sample images ims = create_images(L, 10) + # convolve using coefficients + basis = FLEBasis2D(L, match_fb=False, dtype=ims.dtype) coefs = basis.evaluate_t(ims) coefs_convolved = basis.radial_convolve(coefs, x) imgs_convolved_fle = basis.evaluate(coefs_convolved).asnumpy() diff --git a/tests/test_covar2d_denoiser.py b/tests/test_covar2d_denoiser.py index c9b749335b..ea5410fb34 100644 --- a/tests/test_covar2d_denoiser.py +++ b/tests/test_covar2d_denoiser.py @@ -18,6 +18,9 @@ RadialCTFFilter(5, 200, defocus=d, Cs=2.0, alpha=0.1) for d in np.linspace(1.5e4, 2.5e4, 7) ] + +# For (F)PSWFBasis2D we get off-block entries which are truncated +# when converting to block-diagonal. We filter these warnings. BASIS = [ pytest.param(FBBasis2D, marks=pytest.mark.expensive), FFBBasis2D, From 6ed06437afc50b5ce9e30872a344e25e1bb14adc Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Tue, 10 Sep 2024 13:55:48 -0400 Subject: [PATCH 17/25] Add pytest --strict-warnings to CI workflows. --- .github/workflows/long_workflow.yml | 2 +- .github/workflows/workflow.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/long_workflow.yml b/.github/workflows/long_workflow.yml index ec5714a29e..d483ac5912 100644 --- a/.github/workflows/long_workflow.yml +++ b/.github/workflows/long_workflow.yml @@ -36,6 +36,6 @@ jobs: export OMP_NUM_THREADS=1 ASPIREDIR=${{ env.WORK_DIR }} python -c \ "import aspire; print(aspire.config['ray']['temp_dir'])" - ASPIREDIR=${{ env.WORK_DIR }} python -m pytest -n8 -m "expensive" --durations=0 + ASPIREDIR=${{ env.WORK_DIR }} python -m pytest -n8 -m "expensive" --durations=0 --strict-warnings - name: Cleanup run: rm -rf ${{ env.WORK_DIR }} diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index b2263a460b..ead21b923f 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -99,7 +99,7 @@ jobs: run: | export OMP_NUM_THREADS=2 # -n runs test in parallel using pytest-xdist - pytest -n2 --durations=50 -s + pytest -n2 --durations=50 -s --strict-warnings # Build and Deploy production (main) docs. docs_deploy: @@ -157,7 +157,7 @@ jobs: run: | ASPIREDIR=${{ env.WORK_DIR }} python -c \ "import aspire; print(aspire.config['ray']['temp_dir'])" - ASPIREDIR=${{ env.WORK_DIR }} python -m pytest --durations=50 + ASPIREDIR=${{ env.WORK_DIR }} python -m pytest --durations=50 --strict-warnings - name: Cache Data run: | ASPIREDIR=${{ env.WORK_DIR }} python -c \ @@ -247,4 +247,4 @@ jobs: pip install -e ".[dev]" # install aspire pip freeze - name: Test - run: python -m pytest -n3 --durations=50 + run: python -m pytest -n3 --durations=50 --strict-warnings From 0366a10ce54543f815de1f4069a2acfd57c24b4e Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Tue, 10 Sep 2024 14:15:10 -0400 Subject: [PATCH 18/25] Use PYTHONWARNINGS=error when python runs pytest. --- .github/workflows/long_workflow.yml | 2 +- .github/workflows/workflow.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/long_workflow.yml b/.github/workflows/long_workflow.yml index d483ac5912..a2f2938c8f 100644 --- a/.github/workflows/long_workflow.yml +++ b/.github/workflows/long_workflow.yml @@ -36,6 +36,6 @@ jobs: export OMP_NUM_THREADS=1 ASPIREDIR=${{ env.WORK_DIR }} python -c \ "import aspire; print(aspire.config['ray']['temp_dir'])" - ASPIREDIR=${{ env.WORK_DIR }} python -m pytest -n8 -m "expensive" --durations=0 --strict-warnings + ASPIREDIR=${{ env.WORK_DIR }} PYTHONWARNINGS=error python -m pytest -n8 -m "expensive" --durations=0 - name: Cleanup run: rm -rf ${{ env.WORK_DIR }} diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index ead21b923f..253876f83c 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -157,7 +157,7 @@ jobs: run: | ASPIREDIR=${{ env.WORK_DIR }} python -c \ "import aspire; print(aspire.config['ray']['temp_dir'])" - ASPIREDIR=${{ env.WORK_DIR }} python -m pytest --durations=50 --strict-warnings + ASPIREDIR=${{ env.WORK_DIR }} PYTHONWARNINGS=error python -m pytest --durations=50 - name: Cache Data run: | ASPIREDIR=${{ env.WORK_DIR }} python -c \ @@ -247,4 +247,4 @@ jobs: pip install -e ".[dev]" # install aspire pip freeze - name: Test - run: python -m pytest -n3 --durations=50 --strict-warnings + run: PYTHONWARNINGS=error python -m pytest -n3 --durations=50 From 41e8c57d452e6143a6f26202f0417dfd86a60406 Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Tue, 10 Sep 2024 15:24:35 -0400 Subject: [PATCH 19/25] enforce C order on signal for cufinufft transform. --- src/aspire/nufft/cufinufft.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/aspire/nufft/cufinufft.py b/src/aspire/nufft/cufinufft.py index 218fbd5fb7..fd869aacfd 100644 --- a/src/aspire/nufft/cufinufft.py +++ b/src/aspire/nufft/cufinufft.py @@ -107,7 +107,8 @@ def transform(self, signal): " In the future this will be an error." ) - signal = cp.asarray(signal, dtype=self.complex_dtype) + # Note, if not C order, cuFINUFFT will copy-cast anyway. + signal = cp.asarray(signal, order="C", dtype=self.complex_dtype) sig_shape = signal.shape res_shape = self.num_pts From 3fc856bc99571ffbddbac676c8562e61c6f90ce5 Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Wed, 11 Sep 2024 08:27:53 -0400 Subject: [PATCH 20/25] Skip jobs on CI that will error on cached warnings. ampere, osx, long_running. --- tests/test_volume.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_volume.py b/tests/test_volume.py index ac86c4096b..b6e4f74a89 100644 --- a/tests/test_volume.py +++ b/tests/test_volume.py @@ -813,6 +813,12 @@ def test_transformation_symmetry_warnings(symmetric_vols): assert str(vol_c3.symmetry_group) == "C3" +@pytest.mark.skipif( + (os.getenv("GITHUB_JOB") == "ampere_gpu") + or (os.getenv("GITHUB_JOB") == "osx_arm") + or (os.getenv("GITHUB_JOB") == "expensive_tests"), + reason="Cached warnings will error for these jobs.", +) def test_aglebraic_ops_symmetry_warnings(symmetric_vols): """ A warning should be emitted for add, sub, mult, and div. From b350ea0d9c8bb2e41b137d39649b8f95547af461 Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Wed, 11 Sep 2024 10:28:05 -0400 Subject: [PATCH 21/25] Only check warnings on ampere_gpu job. --- .github/workflows/long_workflow.yml | 2 +- .github/workflows/workflow.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/long_workflow.yml b/.github/workflows/long_workflow.yml index a2f2938c8f..ec5714a29e 100644 --- a/.github/workflows/long_workflow.yml +++ b/.github/workflows/long_workflow.yml @@ -36,6 +36,6 @@ jobs: export OMP_NUM_THREADS=1 ASPIREDIR=${{ env.WORK_DIR }} python -c \ "import aspire; print(aspire.config['ray']['temp_dir'])" - ASPIREDIR=${{ env.WORK_DIR }} PYTHONWARNINGS=error python -m pytest -n8 -m "expensive" --durations=0 + ASPIREDIR=${{ env.WORK_DIR }} python -m pytest -n8 -m "expensive" --durations=0 - name: Cleanup run: rm -rf ${{ env.WORK_DIR }} diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 253876f83c..69156dc0e0 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -99,7 +99,7 @@ jobs: run: | export OMP_NUM_THREADS=2 # -n runs test in parallel using pytest-xdist - pytest -n2 --durations=50 -s --strict-warnings + pytest -n2 --durations=50 -s # Build and Deploy production (main) docs. docs_deploy: @@ -247,4 +247,4 @@ jobs: pip install -e ".[dev]" # install aspire pip freeze - name: Test - run: PYTHONWARNINGS=error python -m pytest -n3 --durations=50 + run: python -m pytest -n3 --durations=50 From 00a02c4021bad3bf226963aef84a377dc4cee39c Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Wed, 11 Sep 2024 10:31:53 -0400 Subject: [PATCH 22/25] remove symmetry warning pytest skips. --- tests/test_volume.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/test_volume.py b/tests/test_volume.py index b6e4f74a89..162904a63c 100644 --- a/tests/test_volume.py +++ b/tests/test_volume.py @@ -814,10 +814,8 @@ def test_transformation_symmetry_warnings(symmetric_vols): @pytest.mark.skipif( - (os.getenv("GITHUB_JOB") == "ampere_gpu") - or (os.getenv("GITHUB_JOB") == "osx_arm") - or (os.getenv("GITHUB_JOB") == "expensive_tests"), - reason="Cached warnings will error for these jobs.", + (os.getenv("GITHUB_JOB") == "ampere_gpu"), + reason="Cached warnings will error for this job.", ) def test_aglebraic_ops_symmetry_warnings(symmetric_vols): """ From a36dfa46b90d5096d36ee31cbd0ae02f9fddec99 Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Wed, 11 Sep 2024 14:28:03 -0400 Subject: [PATCH 23/25] remove unnecesary plt.close() --- tests/test_simulation.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/test_simulation.py b/tests/test_simulation.py index c90caa5bdd..7892a4e8de 100644 --- a/tests/test_simulation.py +++ b/tests/test_simulation.py @@ -39,23 +39,14 @@ def testPixelSize(self): def testImageShow(self): self.sim.images[:].show() - # Explicitly close all figures before making backend changes. - plt.close("all") - @matplotlib_dry_run def testCleanImagesShow(self): self.sim.clean_images[:].show() - # Explicitly close all figures before making backend changes. - plt.close("all") - @matplotlib_dry_run def testProjectionsShow(self): self.sim.projections[:].show() - # Explicitly close all figures before making backend changes. - plt.close("all") - class SimVolTestCase(TestCase): """Test Simulation with Volume provided.""" From 673323a96d362a091dc3bb1caa1de33ceb5d9c7b Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Wed, 11 Sep 2024 14:29:58 -0400 Subject: [PATCH 24/25] unused import --- tests/test_simulation.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_simulation.py b/tests/test_simulation.py index 7892a4e8de..92a29e225e 100644 --- a/tests/test_simulation.py +++ b/tests/test_simulation.py @@ -3,7 +3,6 @@ import tempfile from unittest import TestCase -import matplotlib.pyplot as plt import numpy as np from pytest import raises From 9a0afa95ee86f9a18bc965002c2ea96568c12793 Mon Sep 17 00:00:00 2001 From: Josh Carmichael Date: Wed, 11 Sep 2024 14:35:56 -0400 Subject: [PATCH 25/25] Remove useless test case. --- tests/test_volume.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tests/test_volume.py b/tests/test_volume.py index 162904a63c..1f55645e10 100644 --- a/tests/test_volume.py +++ b/tests/test_volume.py @@ -813,10 +813,6 @@ def test_transformation_symmetry_warnings(symmetric_vols): assert str(vol_c3.symmetry_group) == "C3" -@pytest.mark.skipif( - (os.getenv("GITHUB_JOB") == "ampere_gpu"), - reason="Cached warnings will error for this job.", -) def test_aglebraic_ops_symmetry_warnings(symmetric_vols): """ A warning should be emitted for add, sub, mult, and div. @@ -850,12 +846,6 @@ def test_aglebraic_ops_symmetry_warnings(symmetric_vols): # Should have 4 warnings on record. assert len(record) == 4 - # Check that warning occurs only once per line. - with warnings.catch_warnings(record=True) as record: - for _ in range(5): - vol_c3 + vol_c4 - assert len(record) == 1 - def test_volume_load_with_symmetry(): # Check we can load a Volume with symmetry_group.