def setUp(self): self.dtype = np.float32 # Test Volume v = Volume( np.load(os.path.join(DATA_DIR, "clean70SRibosome_vol.npy")).astype( self.dtype)).downsample(32) # Create Sim object. # Creates 10 projects so there is something to feed FSPCABasis. self.src = Simulation(L=v.resolution, n=10, vols=v, dtype=v.dtype) # Original projection image to transform. self.orig_img = self.src.images(0, 1) # Rotate 90 degrees in cartesian coordinates using third party tool. self.rt90_img = Image(np.rot90(self.orig_img.asnumpy(), axes=(1, 2))) # Prepare a Fourier Bessel Basis self.basis = FFBBasis2D((self.orig_img.res, ) * 2, dtype=self.dtype) self.v1 = self.basis.evaluate_t(self.orig_img) self.v2 = self.basis.evaluate_t(self.rt90_img) # These should _not_ be equal or the test is pointless. self.assertFalse(np.allclose(self.v1, self.v2)) # Prepare a FSPCA Basis too. self.fspca_basis = FSPCABasis(self.src, self.basis)
def testRotate(self): # Now low res (8x8) had problems; # better with odd (7x7), but still not good. # We'll use a higher res test image. # fh = np.load(os.path.join(DATA_DIR, 'ffbbasis2d_xcoeff_in_8_8.npy'))[:7,:7] # Use a real data volume to generate a clean test image. v = Volume( np.load(os.path.join(DATA_DIR, "clean70SRibosome_vol.npy")).astype( np.float64)) src = Simulation(L=v.resolution, n=1, vols=v, dtype=v.dtype) # Extract, this is the original image to transform. x1 = src.images(0, 1) # Rotate 90 degrees in cartesian coordinates. x2 = Image(np.rot90(x1.asnumpy(), axes=(1, 2))) # Express in an FB basis basis = FFBBasis2D((x1.res, ) * 2, dtype=x1.dtype) v1 = basis.evaluate_t(x1) v2 = basis.evaluate_t(x2) v3 = basis.evaluate_t(x1) v4 = basis.evaluate_t(x1) # Reflect in the FB basis space v4 = basis.rotate(v1, 0, refl=[True]) # Rotate in the FB basis space v3 = basis.rotate(v1, 2 * np.pi) v1 = basis.rotate(v1, -np.pi / 2) # Evaluate back into cartesian y1 = basis.evaluate(v1) y2 = basis.evaluate(v2) y3 = basis.evaluate(v3) y4 = basis.evaluate(v4) # Rotate 90 self.assertTrue(np.allclose(y1[0], y2[0], atol=1e-4)) # 2*pi Identity self.assertTrue( np.allclose(x1[0], y3[0], atol=utest_tolerance(self.dtype))) # Refl (flipped using flipud) self.assertTrue(np.allclose(np.flipud(x1[0]), y4[0], atol=1e-4))
def setUp(self): self.dtype = np.float32 self.sim = Simulation( n=1024, unique_filters=[ RadialCTFFilter(defocus=d) for d in np.linspace(1.5e4, 2.5e4, 7) ], dtype=self.dtype, )
def setUp(self): self.resolution = 16 self.dtype = np.float64 # Create some projections v = Volume( np.load(os.path.join(DATA_DIR, "clean70SRibosome_vol.npy")).astype( self.dtype)) v = v.downsample(self.resolution) # Clean self.clean_src = Simulation( L=self.resolution, n=321, vols=v, dtype=self.dtype, ) # With Noise noise_var = 0.01 * np.var(np.sum(v[0], axis=0)) noise_filter = ScalarFilter(dim=2, value=noise_var) self.noisy_src = Simulation( L=self.resolution, n=123, vols=v, dtype=self.dtype, noise_filter=noise_filter, ) # Set up FFB # Setup a Basis self.basis = FFBBasis2D((self.resolution, self.resolution), dtype=self.dtype) # Create Basis, use precomputed Basis self.clean_fspca_basis = FSPCABasis( self.clean_src, self.basis, noise_var=0 ) # Note noise_var assigned zero, skips eigval filtering. # Ceate another fspca_basis, use autogeneration FFB2D Basis self.noisy_fspca_basis = FSPCABasis(self.noisy_src)
def testShift(self): """ Compare shifting using Image with shifting provided by the Basis. Note the Basis shift method converts from FB to Image space and back. """ n_img = 3 test_shift = np.array([10, 2]) # Construct some synthetic data v = Volume( np.load(os.path.join(DATA_DIR, "clean70SRibosome_vol.npy")).astype( np.float64)).downsample(self.L) src = Simulation(L=self.L, n=n_img, vols=v, dtype=np.float64) # Shift images using the Image method directly shifted_imgs = src.images(0, n_img).shift(test_shift) # Convert original images to basis coefficients f_imgs = self.basis.evaluate_t(src.images(0, n_img)) # Use the basis shift method f_shifted_imgs = self.basis.shift(f_imgs, test_shift) # Compute diff between the shifted image sets diff = shifted_imgs.asnumpy() - self.basis.evaluate( f_shifted_imgs).asnumpy() # Compute mask to compare only the core of the shifted images g = grid_2d(self.L, normalized=False) mask = g["r"] > self.L / 2 # Masking values outside radius to 0 diff = np.where(mask, 0, diff) # Compute and check error rmse = np.sqrt(np.mean(np.square(diff), axis=(1, 2))) logger.info(f"RMSE shifted image diffs {rmse}") self.assertTrue(np.allclose(rmse, 0, atol=1e-5))
def setUp(self): self.resolution = 16 self.dtype = np.float32 # Get a volume v = Volume( np.load(os.path.join(DATA_DIR, "clean70SRibosome_vol.npy")).astype( self.dtype)) v = v.downsample(self.resolution) # Create a src from the volume self.src = Simulation( L=self.resolution, n=321, vols=v, dtype=self.dtype, ) # Calculate some projection images self.imgs = self.src.images(0, self.src.n) # Configure an FSPCA basis self.fspca_basis = FSPCABasis(self.src, noise_var=0)
def _getSrc(self): if not hasattr(self, "shifts"): self.shifts = np.zeros((self.n_img, 2)) return Simulation( vols=self.vols, L=self.resolution, n=self.n_img, C=1, angles=self.rots.angles, offsets=self.shifts, amplitudes=np.ones(self.n_img), seed=12345, dtype=self.dtype, )
def setUp(self): self.dtype = np.float32 self.resolution = 8 self.n = 1024 # Generate a stack of images self.sim = sim = Simulation( n=self.n, L=self.resolution, unique_filters=[IdentityFilter()], seed=0, dtype=self.dtype, # We'll use random angles offsets=np.zeros((self.n, 2)), # No offsets amplitudes=np.ones((self.n)), # Constant amplitudes ) # Expose images as numpy array. self.ims_np = sim.images(0, sim.n).asnumpy() self.im = Image(self.ims_np) # Vol estimation requires a 3D basis self.basis = FBBasis3D((self.resolution,) * 3, dtype=self.dtype)
class FSPCATestCase(TestCase): def setUp(self): self.resolution = 16 self.dtype = np.float32 # Get a volume v = Volume( np.load(os.path.join(DATA_DIR, "clean70SRibosome_vol.npy")).astype( self.dtype)) v = v.downsample(self.resolution) # Create a src from the volume self.src = Simulation( L=self.resolution, n=321, vols=v, dtype=self.dtype, ) # Calculate some projection images self.imgs = self.src.images(0, self.src.n) # Configure an FSPCA basis self.fspca_basis = FSPCABasis(self.src, noise_var=0) def testExpandEval(self): coef = self.fspca_basis.expand_from_image_basis(self.imgs) recon = self.fspca_basis.evaluate_to_image_basis(coef) # Check recon is close to imgs rmse = np.sqrt( np.mean(np.square(self.imgs.asnumpy() - recon.asnumpy()))) logger.info(f"FSPCA Expand Eval Image Round Trupe RMSE: {rmse}") self.assertTrue(rmse < utest_tolerance(self.dtype)) def testComplexConversionErrors(self): """ Test we raise when passed incorrect dtypes. Also checks we can handle 0d vector in `to_real`. Most other cases covered by classification unit tests. """ with pytest.raises( TypeError, match="coef provided to to_complex should be real."): _ = self.fspca_basis.to_complex( np.arange(self.fspca_basis.count, dtype=np.complex64)) with pytest.raises( TypeError, match="coef provided to to_real should be complex."): _ = self.fspca_basis.to_real( np.arange(self.fspca_basis.count, dtype=np.float32).flatten()) def testRotate(self): """ Trivial test of rotation in FSPCA Basis. Also covers to_real and to_complex conversions in FSPCA Basis. """ coef = self.fspca_basis.expand_from_image_basis(self.imgs) # rotate by pi rot_coef = self.fspca_basis.rotate(coef, radians=np.pi) rot_imgs = self.fspca_basis.evaluate_to_image_basis(rot_coef) for i, img in enumerate(self.imgs): rmse = np.sqrt(np.mean(np.square(np.flip(img) - rot_imgs[i]))) self.assertTrue(rmse < 10 * utest_tolerance(self.dtype))
# # For now we will build up to the creation and application of synthetic data set based on the real volume data used previously. # %% # ``Simulation`` Class # -------------------- # # Generating realistic synthetic data sources is a common task. # The process of generating then projecting random rotations is integrated into the # `Simulation <https://computationalcryoem.github.io/ASPIRE-Python/aspire.source.html#module-aspire.source.simulation>`_ class. # Using ``Simulation``, we can generate arbitrary numbers of projections for use in experiments. # Later we will demonstrate additional features which allow us to create more realistic data sources. num_imgs = 100 # How many images in our source. # Generate a Simulation instance based on the original volume data. sim = Simulation(L=v.resolution, n=num_imgs, vols=v) # Display the first 10 images sim.images(0, 10).show() # Hi Res # Repeat for the lower resolution (downsampled) volume v2. sim2 = Simulation(L=v2.resolution, n=num_imgs, vols=v2) sim2.images(0, 10).show() # Lo Res # Note both of those simulations have the same rotations # because they had the same seed by default, # We can set our own seed to get a different random samples (of rotations). sim_seed = Simulation(L=v.resolution, n=num_imgs, vols=v, seed=42) sim_seed.images(0, 10).show() # We can also view the rotations used to create these projections # logger.info(sim2.rots) # Commented due to long output
class BispectrumTestCase(TestCase): def setUp(self): self.dtype = np.float32 # Test Volume v = Volume( np.load(os.path.join(DATA_DIR, "clean70SRibosome_vol.npy")).astype( self.dtype)).downsample(32) # Create Sim object. # Creates 10 projects so there is something to feed FSPCABasis. self.src = Simulation(L=v.resolution, n=10, vols=v, dtype=v.dtype) # Original projection image to transform. self.orig_img = self.src.images(0, 1) # Rotate 90 degrees in cartesian coordinates using third party tool. self.rt90_img = Image(np.rot90(self.orig_img.asnumpy(), axes=(1, 2))) # Prepare a Fourier Bessel Basis self.basis = FFBBasis2D((self.orig_img.res, ) * 2, dtype=self.dtype) self.v1 = self.basis.evaluate_t(self.orig_img) self.v2 = self.basis.evaluate_t(self.rt90_img) # These should _not_ be equal or the test is pointless. self.assertFalse(np.allclose(self.v1, self.v2)) # Prepare a FSPCA Basis too. self.fspca_basis = FSPCABasis(self.src, self.basis) def testRotationalInvarianceFB(self): """ Compare FB/FFB bispectrums before and after rotation. Compares a slab of 3d bispectrum (k1 q1) x (k2 q2) x q3, by freq_cutoff of q3 to reduce size. """ # Compute Bispectrum q = 3 # slab cutoff # We'll also excercise some other options to check they don't crash b1 = self.basis.calculate_bispectrum(self.v1, freq_cutoff=q, flatten=True, filter_nonzero_freqs=True) b2 = self.basis.calculate_bispectrum(self.v2, freq_cutoff=q, flatten=True, filter_nonzero_freqs=True) # Bispectrum should be equivalent self.assertTrue(np.allclose(b1, b2)) def testRotationalInvarianceFSPCA(self): """ Compare FSPCA bispctrum before and after rotation. """ # Compute Bispectrum w1 = self.fspca_basis.calculate_bispectrum(self.v1) w2 = self.fspca_basis.calculate_bispectrum(self.v2) # Bispectrum should be equivalent self.assertTrue(np.allclose(w1, w2)) def testRotationalInvarianceFSPCACompressed(self): """ Compare Compressed FSPCA bispctrum before and after rotation. This is most like what is used in practice for RIR. """ # Create a reduced rank (compressed) FSPCABasis, top 100 components. components = 100 compressed_fspca = FSPCABasis(self.src, self.basis, components=components) # Compress using representation in the compressed FSPCA cv1_r = compressed_fspca.expand(self.v1) cv2_r = compressed_fspca.expand(self.v2) # Check we are really compressed self.assertTrue(compressed_fspca.complex_count == components) # Compute Bispectrum w1 = compressed_fspca.calculate_bispectrum(cv1_r) w2 = compressed_fspca.calculate_bispectrum(cv2_r) # Bispectrum should be equivalent self.assertTrue(np.allclose(w1, w2))