-
Notifications
You must be signed in to change notification settings - Fork 26
add unit tests for preprocess pipeline #289
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
1d1216d
Fix the order of Multiple Xform
junchaoxia be1b08e
Add unit tests of preprocess pipeline for issue #234
junchaoxia f011dc5
Improve Multiply Xform
junchaoxia d5b616e
Merge branch 'develop' into preprocess_test and solve conflicts
junchaoxia d2fa582
Solve conflict due to renamed parameters for unique filters
junchaoxia a9ee112
Simplify unit test for invert_contrast
junchaoxia 2627ef0
Use ArraySourceImage to initialize simulation object with negative im…
junchaoxia db0d4ad
Remove noise from unit test of downsample
junchaoxia ef13a52
Use smooth Gaussian density for unit test of downsample
junchaoxia 67b01a4
Merge branch 'develop' into preprocess_test
junchaoxia 161c5a5
Rum commands to improve format
junchaoxia 4ab0da7
Resolve conflict with ScaledFilter
junchaoxia 999145c
Use non-whiting filter for initializing images
junchaoxia db5bf5f
Merge branch 'develop' into preprocess_test and solve conflict
junchaoxia 5f11263
Solve the remain conflicts with develop
junchaoxia 85dbb11
Merge branch 'develop' into preprocess_test
junchaoxia d18f367
Merge branch 'develop' into preprocess_test
junchaoxia 77bfbe8
Merge branch 'develop' into preprocess_test
junchaoxia e6bb24a
Remove PowerFilter and use AnisotropicNoiseEstimator
junchaoxia 2f6e363
Add downsample check for grid points
junchaoxia 20d42ef
Add dtype and atol for tolerance
junchaoxia 934eb94
Scale cummulated norm by image size to remove size dependency
junchaoxia 733aca1
Merge branch 'develop' into preprocess_test
junchaoxia beaea3c
Use anorm to normalize each image instead of whole stack
junchaoxia File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| import os.path | ||
| from unittest import TestCase | ||
|
|
||
| import numpy as np | ||
|
|
||
| from aspire.noise import AnisotropicNoiseEstimator | ||
| from aspire.operators.filters import FunctionFilter, RadialCTFFilter, ScalarFilter | ||
| from aspire.source import ArrayImageSource | ||
| from aspire.source.simulation import Simulation | ||
| from aspire.utils import utest_tolerance | ||
| from aspire.utils.coor_trans import grid_2d, grid_3d | ||
| from aspire.utils.matrix import anorm | ||
| from aspire.volume import Volume | ||
|
|
||
| DATA_DIR = os.path.join(os.path.dirname(__file__), "saved_test_data") | ||
|
|
||
|
|
||
| class PreprocessPLTestCase(TestCase): | ||
| def setUp(self): | ||
|
|
||
| self.L = 64 | ||
| self.n = 128 | ||
| self.dtype = np.float32 | ||
| self.noise_filter = FunctionFilter(lambda x, y: np.exp(-(x ** 2 + y ** 2) / 2)) | ||
|
|
||
| self.sim = Simulation( | ||
| L=self.L, | ||
| n=self.n, | ||
| unique_filters=[ | ||
| RadialCTFFilter(defocus=d) for d in np.linspace(1.5e4, 2.5e4, 7) | ||
| ], | ||
| noise_filter=self.noise_filter, | ||
| dtype=self.dtype, | ||
| ) | ||
| self.imgs_org = self.sim.images(start=0, num=self.n) | ||
|
|
||
| def testPhaseFlip(self): | ||
| self.sim.phase_flip() | ||
| imgs_pf = self.sim.images(start=0, num=self.n) | ||
|
|
||
| # check energy conservation | ||
| self.assertTrue( | ||
| np.allclose( | ||
| anorm(self.imgs_org.asnumpy(), axes=(1, 2)), | ||
| anorm(imgs_pf.asnumpy(), axes=(1, 2)), | ||
| ) | ||
| ) | ||
|
|
||
| def testDownsample(self): | ||
| # generate a 3D map with density decays as Gaussian function | ||
| g3d = grid_3d(self.L, dtype=self.dtype) | ||
| coords = np.array([g3d["x"].flatten(), g3d["y"].flatten(), g3d["z"].flatten()]) | ||
| sigma = 0.2 | ||
| vol = np.exp(-0.5 * np.sum(np.abs(coords / sigma) ** 2, axis=0)).astype( | ||
| self.dtype | ||
| ) | ||
| vol = np.reshape(vol, g3d["x"].shape) | ||
| vols = Volume(vol) | ||
|
|
||
| # set noise to zero and CFT filters to unity for simulation object | ||
| noise_var = 0 | ||
| noise_filter = ScalarFilter(dim=2, value=noise_var) | ||
| sim = Simulation( | ||
| L=self.L, | ||
| n=self.n, | ||
| vols=vols, | ||
| offsets=0.0, | ||
| amplitudes=1.0, | ||
| unique_filters=[ | ||
| ScalarFilter(dim=2, value=1) for d in np.linspace(1.5e4, 2.5e4, 7) | ||
| ], | ||
| noise_filter=noise_filter, | ||
| dtype=self.dtype, | ||
| ) | ||
| # get images before downsample | ||
| imgs_org = sim.images(start=0, num=self.n) | ||
| # get images after downsample | ||
| max_resolution = 32 | ||
| sim.downsample(max_resolution) | ||
| imgs_ds = sim.images(start=0, num=self.n) | ||
|
|
||
| # Check individual grid points | ||
| self.assertTrue( | ||
| np.allclose( | ||
| imgs_org[:, 32, 32], | ||
| imgs_ds[:, 16, 16], | ||
| atol=utest_tolerance(self.dtype), | ||
| ) | ||
| ) | ||
| # check resolution | ||
| self.assertTrue(np.allclose(max_resolution, imgs_ds.shape[1])) | ||
| # check energy conservation after downsample | ||
| self.assertTrue( | ||
| np.allclose( | ||
| anorm(imgs_org.asnumpy(), axes=(1, 2)) / self.L, | ||
| anorm(imgs_ds.asnumpy(), axes=(1, 2)) / max_resolution, | ||
| atol=utest_tolerance(self.dtype), | ||
| ) | ||
| ) | ||
|
|
||
| def testNormBackground(self): | ||
| bg_radius = 1.0 | ||
| grid = grid_2d(self.L) | ||
| mask = grid["r"] > bg_radius | ||
| self.sim.normalize_background() | ||
| imgs_nb = self.sim.images(start=0, num=self.n).asnumpy() | ||
| new_mean = np.mean(imgs_nb[:, mask]) | ||
| new_variance = np.var(imgs_nb[:, mask]) | ||
|
|
||
| # new mean of noise should be close to zero and variance should be close to 1 | ||
| self.assertTrue(new_mean < 1e-7 and abs(new_variance - 1) < 1e-7) | ||
|
|
||
| def testWhiten(self): | ||
| noise_estimator = AnisotropicNoiseEstimator(self.sim) | ||
| self.sim.whiten(noise_estimator.filter) | ||
janden marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| imgs_wt = self.sim.images(start=0, num=self.n).asnumpy() | ||
|
|
||
| # calculate correlation between two neighboring pixels from background | ||
| corr_coef = np.corrcoef( | ||
| imgs_wt[:, self.L - 1, self.L - 1], imgs_wt[:, self.L - 2, self.L - 1] | ||
| ) | ||
|
|
||
| # correlation matrix should be close to identity | ||
| self.assertTrue(np.allclose(np.eye(2), corr_coef, atol=1e-1)) | ||
|
|
||
| def testInvertContrast(self): | ||
| sim1 = self.sim | ||
| imgs1 = sim1.images(start=0, num=128) | ||
| sim1.invert_contrast() | ||
| imgs1_rc = sim1.images(start=0, num=128) | ||
| # need to set the negative images to the second simulation object | ||
| sim2 = ArrayImageSource(-imgs1) | ||
| sim2.invert_contrast() | ||
| imgs2_rc = sim2.images(start=0, num=128) | ||
|
|
||
| # all images should be the same after inverting contrast | ||
| self.assertTrue(np.allclose(imgs1_rc.asnumpy(), imgs2_rc.asnumpy())) | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.