Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    def src_backward(self, mean_vol, noise_variance, shrink_method=None):
        """
        Apply adjoint mapping to source

        :return: The sum of the outer products of the mean-subtracted images in `src`, corrected by the expected noise
        contribution and expressed as coefficients of `basis`.
        """
        covar_b = np.zeros((self.L, self.L, self.L, self.L, self.L, self.L),
                           dtype=self.as_type)

        for i in range(0, self.n, self.batch_size):
            im = self.src.images(i, self.batch_size)
            batch_n = im.shape[-1]
            im_centered = im - self.src.vol_forward(mean_vol, i,
                                                    self.batch_size)

            im_centered_b = np.zeros((self.L, self.L, self.L, batch_n),
                                     dtype=self.as_type)
            for j in range(batch_n):
                im_centered_b[:, :, :, j] = self.src.im_backward(
                    Image(im_centered[:, :, j]), i + j)
            im_centered_b = vol_to_vec(im_centered_b)

            covar_b += vecmat_to_volmat(
                im_centered_b @ im_centered_b.T) / self.n

        covar_b_coeff = self.basis.mat_evaluate_t(covar_b)
        return self._shrink(covar_b_coeff, noise_variance, shrink_method)
Exemplo n.º 3
0
    def _images(self, start=0, num=np.inf, indices=None, batch_size=512):
        """
        Internal function to return a set of images after denoising

        :param start: The inclusive start index from which to return images.
        :param num: The exclusive end index up to which to return images.
        :param num: The indices of images to return.
        :return: an `Image` object after denoisng.
        """
        if indices is None:
            indices = np.arange(start, min(start + num, self.n))
        else:
            start = indices.min()
        end = indices.max()

        nimgs = len(indices)
        im = np.empty((nimgs, self.L, self.L))

        logger.info(f"Loading {nimgs} images complete")
        for istart in range(start, end + 1, batch_size):
            imgs_denoised = self.denoiser.images(istart, batch_size)
            iend = min(istart + batch_size, end + 1)
            im[istart:iend] = imgs_denoised.data

        return Image(im)
Exemplo n.º 4
0
    def eval_filters(self, im_orig, start=0, num=np.inf, indices=None):
        if not isinstance(im_orig, Image):
            logger.warning(
                f"eval_filters passed {type(im_orig)} instead of Image instance"
            )
            # for now just convert it
            im = Image(im_orig)

        im = im_orig.copy()

        if indices is None:
            indices = np.arange(start, min(start + num, self.n))

        for i, filt in enumerate(self.unique_filters):
            idx_k = np.where(self.filter_indices[indices] == i)[0]
            if len(idx_k) > 0:
                im[idx_k] = Image(im[idx_k]).filter(filt).asnumpy()

        return im
Exemplo n.º 5
0
    def output(
        self,
        classes,
        classes_refl,
        rot,
        shifts=None,
        coefs=None,
    ):
        """
        Return class averages.

        :param classes: class indices (refering to src). (n_img, n_nbor)
        :param classes_refl: Bool representing whether to reflect image in `classes`
        :param rot: Array of in-plane rotation angles (Radians) of image in `classes`
        :param shifts: Optional array of shifts for image in `classes`.
        :coefs: Optional Fourier bessel coefs (avoids recomputing).
        :return: Stack of Synthetic Class Average images as Image instance.
        """

        logger.info(f"Select {self.n_classes} Classes from Nearest Neighbors")
        # generate indices for random sample (can do something smart with corr later).
        # For testing just take the first n_classes so it matches earlier plots for manual comparison
        # This is assumed to be reasonably random.
        selection = np.arange(self.n_classes)

        imgs = self.src.images(0, self.src.n)
        fb_avgs = np.empty((self.n_classes, self.fb_basis.count),
                           dtype=self.src.dtype)

        for i in tqdm(range(self.n_classes)):
            j = selection[i]
            # Get the neighbors
            neighbors_ids = classes[j]

            # Get coefs in Fourier Bessel Basis if not provided as an argument.
            if coefs is None:
                neighbors_imgs = Image(imgs[neighbors_ids])
                if shifts is not None:
                    neighbors_imgs.shift(shifts[i])
                neighbors_coefs = self.fb_basis.evaluate_t(neighbors_imgs)
            else:
                neighbors_coefs = coefs[neighbors_ids]
                if shifts is not None:
                    neighbors_coefs = self.fb_basis.shift(
                        neighbors_coefs, shifts[i])

            # Rotate in Fourier Bessel
            neighbors_coefs = self.fb_basis.rotate(neighbors_coefs, rot[j],
                                                   classes_refl[j])

            # Averaging in FB
            fb_avgs[i] = np.mean(neighbors_coefs, axis=0)

        # Now we convert the averaged images from FB to Cartesian.
        return ArrayImageSource(self.fb_basis.evaluate(fb_avgs))
Exemplo n.º 6
0
    def _forward(self, im, indices):
        im = im.copy()

        for i, idx in enumerate(indices):
            # Note: The following random seed behavior is directly taken from MATLAB Cov3D code.
            random_seed = self.seed + 191 * (idx + 1)
            im_s = randn(2 * im.res, 2 * im.res, seed=random_seed)
            im_s = Image(im_s).filter(self.noise_filter)[:, :, 0]
            im[:, :, i] += im_s[:im.res, :im.res]

        return im
Exemplo n.º 7
0
    def eval_filters(self, im_orig, start=0, num=np.inf, indices=None):
        im = im_orig.copy()
        if indices is None:
            indices = np.arange(start, min(start + num, self.n))

        unique_filters = set(self.filters)
        for f in unique_filters:
            idx_k = np.where(self.filters[indices] == f)[0]
            if len(idx_k) > 0:
                im[:, :, idx_k] = Image(im[:, :, idx_k]).filter(f).asnumpy()

        return im
Exemplo n.º 8
0
    def setUp(self):
        with importlib_resources.path(tests.saved_test_data,
                                      "sample_data_model.star") as path:
            self.starfile = StarFile(path)

        # Independent Image object for testing Image source methods
        L = 768
        self.im = Image(misc.face(gray=True).astype("float64")[:L, :L])
        self.img_src = ArrayImageSource(self.im)

        # We also want to flex the stack logic.
        self.n = 21
        im_stack = np.broadcast_to(self.im.data, (self.n, L, L))
        # make each image methodically different
        im_stack = np.multiply(im_stack, np.arange(self.n)[:, None, None])
        self.im_stack = Image(im_stack)
        self.img_src_stack = ArrayImageSource(self.im_stack)

        # Create a tmpdir object for this test instance
        self._tmpdir = tempfile.TemporaryDirectory()
        # Get the directory from the name attribute of the instance
        self.tmpdir = self._tmpdir.name
Exemplo n.º 9
0
 def vol_forward(self, vol, start, num):
     """
     Apply forward image model to volume
     :param vol: A volume of size L-by-L-by-L.
     :param start: Start index of image to consider
     :param num: Number of images to consider
     :return: The images obtained from volume by projecting, applying CTFs, translating, and multiplying by the
         amplitude.
     """
     all_idx = np.arange(start, min(start + num, self.n))
     im = vol_project(vol, self.rots[all_idx, :, :])
     im = self.eval_filters(im, start, num)
     im = Image(im).shift(self.offsets[all_idx, :])
     im *= np.broadcast_to(self.amplitudes[all_idx],
                           (self.L, self.L, len(all_idx)))
     return im
Exemplo n.º 10
0
 def testFBBasis2DEvaluate_t(self):
     v = np.load(os.path.join(DATA_DIR, "fbbasis_coefficients_8_8.npy")).T  # RCOPT
     # While FB can accept arrays, prefable to pass FB2D and FFB2D Image instances.
     img = Image(v.astype(self.dtype))
     result = self.basis.evaluate_t(img)
     self.assertTrue(
         np.allclose(
             result,
             [
                 0.10761825,
                 0.12291151,
                 0.00836345,
                 -0.0619454,
                 -0.0483326,
                 0.01053718,
                 0.03977641,
                 0.03420101,
                 -0.0060131,
                 -0.02970658,
                 -0.0151334,
                 -0.00017575,
                 -0.03987446,
                 -0.00257069,
                 -0.0006621,
                 -0.00975174,
                 0.00108047,
                 0.00072022,
                 0.00753342,
                 0.00604493,
                 0.00024362,
                 -0.01711248,
                 -0.01387371,
                 0.00112805,
                 0.02407385,
                 0.00376325,
                 0.00081128,
                 0.00951368,
                 -0.00557536,
                 0.01087579,
                 0.00255393,
                 -0.00525156,
                 -0.00839695,
                 0.00802198,
             ],
             atol=utest_tolerance(self.dtype),
         )
     )
Exemplo n.º 11
0
    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))
Exemplo n.º 12
0
    def _images(self, start=0, num=np.inf, indices=None):
        if indices is None:
            indices = np.arange(start, min(start + num, self.n))
        else:
            start = indices.min()
        logger.info(f"Loading {len(indices)} images from STAR file")

        def load_single_mrcs(filepath, df):
            arr = mrcfile.open(filepath).data
            # if the stack only contains one image, arr will have shape (resolution, resolution)
            # the code below reshapes it to (1, resolution, resolution)
            if len(arr.shape) == 2:
                arr = arr.reshape((1,) + arr.shape)
            data = arr[df["__mrc_index"] - 1, :, :]

            return df.index, data

        n_workers = self.n_workers
        if n_workers < 0:
            n_workers = cpu_count() - 1

        df = self._metadata.loc[indices]
        im = np.empty(
            (len(indices), self._original_resolution, self._original_resolution),
            dtype=self.dtype,
        )

        groups = df.groupby("__mrc_filepath")
        n_workers = min(n_workers, len(groups))

        with futures.ThreadPoolExecutor(n_workers) as executor:
            to_do = []
            for filepath, _df in groups:
                future = executor.submit(load_single_mrcs, filepath, _df)
                to_do.append(future)

            for future in futures.as_completed(to_do):
                data_indices, data = future.result()
                im[data_indices - start] = data

        logger.info(f"Loading {len(indices)} images complete")

        return Image(im)
Exemplo n.º 13
0
    def images(self, start, num, *args, **kwargs):
        """
        Return images from this ImageSource as an Image object.
        :param start: The inclusive start index from which to return images.
        :param num: The exclusive end index up to which to return images.
        :param args: Any additional positional arguments to pass on to the `ImageSource`'s underlying `_images` method.
        :param kwargs: Any additional keyword arguments to pass on to the `ImageSource`'s underlying `_images` method.
        :return: an `Image` object.
        """
        indices = np.arange(start, min(start + num, self.n))

        if self._im is not None:
            logger.info(f'Loading images from cache')
            im = Image(self._im[:, :, indices])
        else:
            im = self._images(indices=indices, *args, **kwargs)
            im = self.generation_pipeline.forward(im, indices=indices)

        logger.info(f'Loaded {len(indices)} images')
        return im
Exemplo n.º 14
0
    def estimate_psd(self, blocks, tapers_1d):
        """
        Estimate the power spectrum of the micrograph using the multi-taper method

        :param blocks: 3-D NumPy array containing windows extracted from the micrograph in the preprocess function.
        :param tapers_1d: NumPy array of data tapers.
        :return: NumPy array of estimated power spectrum.
        """

        num_1d_tapers = tapers_1d.shape[-1]
        tapers_1d = tapers_1d.astype(complex_type(self.dtype), copy=False)

        blocks_mt = np.zeros(blocks[0, :, :].shape, dtype=self.dtype)

        blocks_tapered = np.zeros(blocks[0, :, :].shape,
                                  dtype=complex_type(self.dtype))

        taper_2d = np.zeros((blocks.shape[1], blocks.shape[2]),
                            dtype=complex_type(self.dtype))

        for ax1 in range(num_1d_tapers):
            for ax2 in range(num_1d_tapers):
                np.matmul(
                    tapers_1d[:, ax1, np.newaxis],
                    tapers_1d[:, ax2, np.newaxis].T,
                    out=taper_2d,
                )

                for m in range(blocks.shape[0]):
                    np.multiply(blocks[m, :, :], taper_2d, out=blocks_tapered)
                    blocks_mt_post_fft = fft.fftn(blocks_tapered,
                                                  axes=(-2, -1))
                    blocks_mt += abs2(blocks_mt_post_fft)

        blocks_mt /= blocks.shape[0]**2
        blocks_mt /= tapers_1d.shape[0]**2

        amplitude_spectrum = fft.fftshift(
            blocks_mt)  # max difference 10^-13, max relative difference 10^-14

        return Image(amplitude_spectrum)
Exemplo n.º 15
0
    def __init__(self, im, metadata=None, angles=None):
        """
        Initialize from an `Image` object
        :param im: An `Image` or Numpy array object representing image data served up by this `ImageSource`.
        In the case of a Numpy array, attempts to create an 'Image' object.
        :param metadata: A Dataframe of metadata information corresponding to this ImageSource's images
        :param angles: Optional n-by-3 array of rotation angles corresponding to `im`.
        """

        if not isinstance(im, Image):
            logger.info(
                "Attempting to create an Image object from Numpy array.")
            try:
                im = Image(im)
            except Exception as e:
                raise RuntimeError(
                    "Creating Image object from Numpy array failed."
                    f" Original error: {str(e)}")

        super().__init__(L=im.res,
                         n=im.n_images,
                         dtype=im.dtype,
                         metadata=metadata,
                         memory=None)

        self._cached_im = im

        # Create filter indices, these are required to pass unharmed through filter eval code
        #   that is potentially called by other methods later.
        self.filter_indices = np.zeros(self.n)
        self.unique_filters = [IdentityFilter()]

        # Optionally populate angles/rotations.
        if angles is not None:
            if angles.shape != (self.n, 3):
                raise ValueError(f"Angles should be shape {(self.n, 3)}")
            # This will populate `_rotations`,
            #   which is exposed by properties `angles` and `rots`.
            self.angles = angles
Exemplo n.º 16
0
    def projections(self, start=0, num=np.inf, indices=None):
        """
        Return projections of generated volumes, without applying filters/shifts/amplitudes/noise
        :param start: start index (0-indexed) of the start image to return
        :param num: Number of images to return. If None, *all* images are returned.
        :param indices: A numpy array of image indices. If specified, start and num are ignored.
        :return: An ndarray of shape (L, L, num), L being the size of each image.
        """
        if indices is None:
            indices = np.arange(start, min(start + num, self.n))

        im = np.zeros((self.L, self.L, len(indices)))

        states = self.states[indices]
        unique_states = np.unique(states)
        for k in unique_states:
            vol_k = self.vols[:, :, :, k - 1]
            idx_k = np.where(states == k)[0]
            rot = self.rots[indices[idx_k], :, :]

            im_k = vol_project(vol_k, rot)
            im[:, :, idx_k] = im_k
        return Image(im)
Exemplo n.º 17
0
    def _read(self):
        with mrcfile.open(self.filepath, permissive=self.permissive) as mrc:
            im = mrc.data
            if im.dtype != self.dtype:
                logger.info(f"Micrograph read casting {self.filepath}"
                            f" data to {self.dtype} from {im.dtype}.")
                im = im.astype(self.dtype)

        # NOTE: For multiple mrc files, mrcfile returns an ndarray with
        # (shape n_images, height, width)

        # Discard outer pixels
        im = im[..., self.margin_top:-self.margin_bottom if self.
                margin_bottom is not None else None,
                self.margin_left:-self.margin_right if self.
                margin_right is not None else None, ]

        if self.square:
            side_length = min(im.shape[-2], im.shape[-1])
            im = im[..., :side_length, :side_length]

        if self.shrink_factor is not None:
            size = tuple((np.array(im.shape) /
                          config.apple.mrc_shrink_factor).astype(int))
            im = np.array(
                PILImage.fromarray(im).resize(size, PILImage.BICUBIC))

        if self.gauss_filter_size is not None:
            im = signal.correlate(
                im,
                Micrograph.gaussian_filter(self.gauss_filter_size,
                                           self.gauss_filter_sigma),
                "same",
            )

        self.im = Image(im)
        self.shape = self.im.shape
    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)
Exemplo n.º 19
0
    def projections(self, start=0, num=np.inf, indices=None):
        """
        Return projections of generated volumes, without applying filters/shifts/amplitudes/noise
        :param start: start index (0-indexed) of the start image to return
        :param num: Number of images to return. If None, *all* images are returned.
        :param indices: A numpy array of image indices. If specified, start and num are ignored.
        :return: An Image instance.
        """
        if indices is None:
            indices = np.arange(start, min(start + num, self.n))

        im = np.zeros((len(indices), self._original_L, self._original_L),
                      dtype=self.dtype)

        states = self.states[indices]
        unique_states = np.unique(states)
        for k in unique_states:
            idx_k = np.where(states == k)[0]
            rot = self.rots[indices[idx_k], :, :]

            im_k = self.vols.project(vol_idx=k - 1, rot_matrices=rot)
            im[idx_k, :, :] = im_k.asnumpy()

        return Image(im)
Exemplo n.º 20
0
    def _images(self, start=0, num=np.inf, indices=None):
        if indices is None:
            indices = np.arange(start, min(start + num, self.n))
        else:
            start = indices.min()
        logger.info(f'Loading {len(indices)} images from STAR file')

        def load_single_mrcs(filepath, df):
            arr = mrcfile.open(filepath).data
            data = arr[df['__mrc_index'] - 1, :, :].T

            return df.index, data

        n_workers = self.n_workers
        if n_workers < 0:
            n_workers = cpu_count() - 1

        df = self._metadata.loc[indices]
        im = np.empty((self._original_resolution, self._original_resolution, len(indices)))

        groups = df.groupby('__mrc_filepath')
        n_workers = min(n_workers, len(groups))

        with futures.ThreadPoolExecutor(n_workers) as executor:
            to_do = []
            for filepath, _df in groups:
                future = executor.submit(load_single_mrcs, filepath, _df)
                to_do.append(future)

            for future in futures.as_completed(to_do):
                data_indices, data = future.result()
                im[:, :, data_indices-start] = data

        logger.info(f'Loading {len(indices)} images complete')

        return Image(im)
Exemplo n.º 21
0
 def _images(self, start=0, num=np.inf, indices=None):
     if indices is None:
         indices = np.arange(start, min(start + num, self.n))
     return Image(self.im[:, :, indices])
Exemplo n.º 22
0
 def setUp(self):
     # numpy array for top-level functions that directly expect it
     self.im_np = misc.face(
         gray=True).astype('float64')[:768, :768][:, :, np.newaxis]
     # Independent Image object for testing Image methods
     self.im = Image(misc.face(gray=True).astype('float64')[:768, :768])
Exemplo n.º 23
0
n_pixels = min(stock_img.shape)
stock_img = stock_img[0:n_pixels, 0:n_pixels]
# Normalize to [0,1]
stock_img /= np.max(stock_img)


# %%
# Add Noise to the Image
# ----------------------
# Now that we have an example array, we will begin using the ASPIRE toolkit.
# First we will make an ASPIRE Image instance out of our data.
# This is a light wrapper over the numpy array. Many ASPIRE internals
# are built around an ``Image`` class.

# Construct the Image class by passing it an array of data.
img = Image(stock_img)
# Downsample (just to speeds things up)
new_resolution = img.res // 4
img = img.downsample(new_resolution)


# We will begin processing by adding some noise.
# We would like to create uniform noise for a 2d image with prescibed variance,
noise_var = np.var(img.asnumpy()) * 5
noise_filter = ScalarFilter(dim=2, value=noise_var)

# Then create a NoiseAdder.
noise = NoiseAdder(seed=123, noise_filter=noise_filter)

# We can apply the NoiseAdder to our image data.
img_with_noise = noise.forward(img)
Exemplo n.º 24
0
    def evaluate_t(self, x):
        """
        Evaluate coefficient in FB basis from those in standard 2D coordinate basis

        :param x: The Image instance representing coefficient array in the
        standard 2D coordinate basis to be evaluated.
        :return v: The evaluation of the coefficient array `v` in the FB basis.
            This is an array of vectors whose last dimension equals `self.count`
            and whose first dimension correspond to `x.n_images`.
        """

        if x.dtype != self.dtype:
            logger.warning(
                f"{self.__class__.__name__}::evaluate_t"
                f" Inconsistent dtypes v: {x.dtype} self: {self.dtype}")

        if not isinstance(x, Image):
            logger.warning(f"{self.__class__.__name__}::evaluate_t"
                           " passed numpy array instead of Image.")
            x = Image(x)

        # get information on polar grids from precomputed data
        n_theta = np.size(self._precomp["freqs"], 2)
        n_r = np.size(self._precomp["freqs"], 1)
        freqs = np.reshape(self._precomp["freqs"], (2, n_r * n_theta))

        # number of 2D image samples
        n_images = x.n_images
        x_data = x.data

        # resamping x in a polar Fourier gird using nonuniform discrete Fourier transform
        pf = nufft(x_data, 2 * pi * freqs)
        pf = np.reshape(pf, (n_images, n_r, n_theta))

        # Recover "negative" frequencies from "positive" half plane.
        pf = np.concatenate((pf, pf.conjugate()), axis=2)

        # evaluate radial integral using the Gauss-Legendre quadrature rule
        for i_r in range(0, n_r):
            pf[:, i_r, :] = pf[:, i_r, :] * (self._precomp["gl_weights"][i_r] *
                                             self._precomp["gl_nodes"][i_r])

        #  1D FFT on the angular dimension for each concentric circle
        pf = 2 * pi / (2 * n_theta) * xp.asnumpy(fft.fft(xp.asarray(pf)))

        # This only makes it easier to slice the array later.
        v = np.zeros((n_images, self.count), dtype=x.dtype)

        # go through each basis function and find the corresponding coefficient
        ind = 0
        idx = ind + np.arange(self.k_max[0])
        mask = self._indices["ells"] == 0

        # include the normalization factor of angular part into radial part
        radial_norm = self._precomp["radial"] / np.expand_dims(
            self.angular_norms, 1)
        v[:, mask] = pf[:, :, 0].real @ radial_norm[idx].T
        ind = ind + np.size(idx)

        ind_pos = ind
        for ell in range(1, self.ell_max + 1):
            idx = ind + np.arange(self.k_max[ell])
            idx_pos = ind_pos + np.arange(self.k_max[ell])
            idx_neg = idx_pos + self.k_max[ell]

            v_ell = pf[:, :, ell] @ radial_norm[idx].T

            if np.mod(ell, 2) == 0:
                v_pos = np.real(v_ell)
                v_neg = -np.imag(v_ell)
            else:
                v_pos = np.imag(v_ell)
                v_neg = np.real(v_ell)

            v[:, idx_pos] = v_pos
            v[:, idx_neg] = v_neg

            ind = ind + np.size(idx)

            ind_pos = ind_pos + 2 * self.k_max[ell]

        return v
Exemplo n.º 25
0
    def evaluate(self, v):
        """
        Evaluate coefficients in standard 2D coordinate basis from those in FB basis

        :param v: A coefficient vector (or an array of coefficient vectors)
            in FB basis to be evaluated. The last dimension must equal `self.count`.
        :return x: The evaluation of the coefficient vector(s) `x` in standard 2D
            coordinate basis. This is Image instance with resolution of `self.sz`
            and the first dimension correspond to remaining dimension of `v`.
        """

        if v.dtype != self.dtype:
            logger.debug(
                f"{self.__class__.__name__}::evaluate"
                f" Inconsistent dtypes v: {v.dtype} self: {self.dtype}")

        sz_roll = v.shape[:-1]
        v = v.reshape(-1, self.count)

        # number of 2D image samples
        n_data = v.shape[0]

        # get information on polar grids from precomputed data
        n_theta = np.size(self._precomp["freqs"], 2)
        n_r = np.size(self._precomp["freqs"], 1)

        # go through  each basis function and find corresponding coefficient
        pf = np.zeros((n_data, 2 * n_theta, n_r),
                      dtype=complex_type(self.dtype))
        mask = self._indices["ells"] == 0

        ind = 0

        idx = ind + np.arange(self.k_max[0], dtype=int)

        # include the normalization factor of angular part into radial part
        radial_norm = self._precomp["radial"] / np.expand_dims(
            self.angular_norms, 1)
        pf[:, 0, :] = v[:, mask] @ radial_norm[idx]
        ind = ind + np.size(idx)

        ind_pos = ind

        for ell in range(1, self.ell_max + 1):
            idx = ind + np.arange(self.k_max[ell], dtype=int)
            idx_pos = ind_pos + np.arange(self.k_max[ell], dtype=int)
            idx_neg = idx_pos + self.k_max[ell]

            v_ell = (v[:, idx_pos] - 1j * v[:, idx_neg]) / 2.0

            if np.mod(ell, 2) == 1:
                v_ell = 1j * v_ell

            pf_ell = v_ell @ radial_norm[idx]
            pf[:, ell, :] = pf_ell

            if np.mod(ell, 2) == 0:
                pf[:, 2 * n_theta - ell, :] = pf_ell.conjugate()
            else:
                pf[:, 2 * n_theta - ell, :] = -pf_ell.conjugate()

            ind = ind + np.size(idx)
            ind_pos = ind_pos + 2 * self.k_max[ell]

        # 1D inverse FFT in the degree of polar angle
        pf = 2 * pi * xp.asnumpy(fft.ifft(xp.asarray(pf), axis=1))

        # Only need "positive" frequencies.
        hsize = int(np.size(pf, 1) / 2)
        pf = pf[:, 0:hsize, :]

        for i_r in range(0, n_r):
            pf[..., i_r] = pf[..., i_r] * (self._precomp["gl_weights"][i_r] *
                                           self._precomp["gl_nodes"][i_r])

        pf = np.reshape(pf, (n_data, n_r * n_theta))

        # perform inverse non-uniformly FFT transform back to 2D coordinate basis
        freqs = m_reshape(self._precomp["freqs"], (2, n_r * n_theta))

        x = 2 * anufft(pf, 2 * pi * freqs, self.sz, real=True)

        # Return X as Image instance with the last two dimensions as *self.sz
        x = x.reshape((*sz_roll, *self.sz))

        return Image(x)
Exemplo n.º 26
0
# To be consistent with the Matlab version in the numbers, we need to use the statements as below:
logger.info(
    'Generate random distributed rotation angles and obtain corresponding 2D clean images.'
)
rots = qrand_rots(num_imgs, seed=0)
imgs_clean = vol2img(sim.vols[..., 0], rots)

# Assign the CTF information and index for each image
h_idx = np.array([filters.index(f) for f in sim.filters])

# Evaluate CTF in the 8X8 FB basis
h_ctf_fb = [filt.fb_mat(ffbbasis) for filt in filters]

# Apply the CTF to the clean images.
logger.info('Apply CTF filters to clean images.')
imgs_ctf_clean = Image(sim.eval_filters(imgs_clean))
sim.cache(imgs_ctf_clean)

# imgs_ctf_clean is an Image object. Convert to numpy array for subsequent statements
imgs_ctf_clean = imgs_ctf_clean.asnumpy()

# Apply the noise at the desired singal-noise ratio to the filtered clean images
logger.info('Apply noise filters to clean images.')
power_clean = anorm(imgs_ctf_clean)**2 / np.size(imgs_ctf_clean)
noise_var = power_clean / sn_ratio
imgs_noise = imgs_ctf_clean + np.sqrt(noise_var) * randn(
    img_size, img_size, num_imgs, seed=0)

# Expand the images, both clean and noisy, in the Fourier-Bessel basis. This
# can be done exactly (that is, up to numerical precision) using the
# `basis.expand` function, but for our purposes, an approximation will do.
Exemplo n.º 27
0
    def _forward(self, im, indices):
        im_in = im.asnumpy()
        im_out = self.lambda_fun(im_in, *self.args, **self.kwargs)

        return Image(im_out)
Exemplo n.º 28
0
    def testPolarBasis2DEvaluate_t(self):
        x = Image(
            np.array(
                [
                    [
                        0.00000000e00,
                        0.00000000e00,
                        0.00000000e00,
                        0.00000000e00,
                        -1.08106869e-17,
                        0.00000000e00,
                        0.00000000e00,
                        0.00000000e00,
                    ],
                    [
                        0.00000000e00,
                        0.00000000e00,
                        -6.40456062e-03,
                        -3.32961020e-03,
                        -1.36887927e-02,
                        -5.42770488e-03,
                        7.63680861e-03,
                        0.00000000e00,
                    ],
                    [
                        0.00000000e00,
                        3.16377602e-03,
                        -9.31273350e-03,
                        9.46128404e-03,
                        1.93239220e-02,
                        3.79891953e-02,
                        1.06841173e-02,
                        -2.36467925e-03,
                    ],
                    [
                        0.00000000e00,
                        1.72736955e-03,
                        -1.00710814e-02,
                        4.93520304e-02,
                        3.77702656e-02,
                        6.57365438e-02,
                        3.94739462e-03,
                        -4.41228496e-03,
                    ],
                    [
                        4.01551066e-18,
                        -3.08071647e-03,
                        -1.61670565e-02,
                        8.66886286e-02,
                        5.09898409e-02,
                        7.19313349e-02,
                        1.68313715e-02,
                        5.19180892e-03,
                    ],
                    [
                        0.00000000e00,
                        2.87262215e-03,
                        -3.37732956e-02,
                        4.51706505e-02,
                        5.72215879e-02,
                        4.63553081e-02,
                        1.86552175e-03,
                        1.12608805e-02,
                    ],
                    [
                        0.00000000e00,
                        2.77905016e-03,
                        -2.77499404e-02,
                        -4.02645374e-02,
                        -1.54969139e-02,
                        -1.66229153e-02,
                        -2.07389259e-02,
                        6.64060546e-03,
                    ],
                    [
                        0.00000000e00,
                        0.00000000e00,
                        5.20080934e-03,
                        -1.06788196e-02,
                        -1.14761672e-02,
                        -1.27443126e-02,
                        -1.15563484e-02,
                        0.00000000e00,
                    ],
                ],
                dtype=self.dtype,
            ).T)  # RCOPT

        pf = self.basis.evaluate_t(x)
        result = np.array(
            [
                0.38243133 + 6.66608316e-18j,
                0.3249317 - 1.47839074e-01j,
                0.14819172 + 3.78171168e-03j,
                -0.22808599 + 5.29338933e-02j,
                0.38243133 + 6.66608316e-18j,
                0.34595014 - 1.06355385e-01j,
                0.15519289 - 4.75602164e-02j,
                -0.22401193 + 4.33128746e-03j,
                0.38243133 + 6.66608316e-18j,
                0.36957165 - 5.69575709e-02j,
                0.17389327 - 5.53498385e-02j,
                -0.11601473 - 1.35405676e-02j,
                0.38243133 + 6.66608316e-18j,
                0.39045046 - 2.17911945e-03j,
                0.18146449 - 1.37089189e-02j,
                -0.02110144 + 6.65071497e-03j,
                0.38243133 + 6.66608316e-18j,
                0.4063995 + 5.21354967e-02j,
                0.15674204 + 3.85815662e-02j,
                -0.02886296 + 3.91489615e-02j,
                0.38243133 + 6.66608316e-18j,
                0.41872477 + 9.98946906e-02j,
                0.11862477 + 5.15231952e-02j,
                -0.05298751 + 1.95319478e-02j,
                0.38243133 + 6.66608316e-18j,
                0.43013599 + 1.38307796e-01j,
                0.10075763 + 1.25689289e-02j,
                -0.04052728 - 5.66863498e-02j,
                0.38243133 + 6.66608316e-18j,
                0.44144497 + 1.68826980e-01j,
                0.11446016 - 4.53003874e-02j,
                -0.03546515 - 1.13544145e-01j,
                0.38243133 + 6.66608316e-18j,
                0.44960099 + 1.94794929e-01j,
                0.15053714 - 8.11915305e-02j,
                -0.04800556 - 1.15828804e-01j,
                0.38243133 + 6.66608316e-18j,
                0.44872328 + 2.17957567e-01j,
                0.19116871 - 7.99536373e-02j,
                -0.05683092 - 9.72225058e-02j,
                0.38243133 + 6.66608316e-18j,
                0.43379428 + 2.36681249e-01j,
                0.21025378 - 5.48466438e-02j,
                -0.05318826 - 8.54948014e-02j,
                0.38243133 + 6.66608316e-18j,
                0.40485577 + 2.47073481e-01j,
                0.18680217 - 3.31766116e-02j,
                -0.06674163 - 7.94216591e-02j,
                0.38243133 + 6.66608316e-18j,
                0.36865853 + 2.45913767e-01j,
                0.13660805 - 3.68947359e-02j,
                -0.11467046 - 8.49198927e-02j,
                0.38243133 + 6.66608316e-18j,
                0.33597018 + 2.32971425e-01j,
                0.1072859 - 6.24686168e-02j,
                -0.12932565 - 1.06139634e-01j,
                0.38243133 + 6.66608316e-18j,
                0.31616666 + 2.10791785e-01j,
                0.11876919 - 7.93812474e-02j,
                -0.1094488 - 1.20159845e-01j,
                0.38243133 + 6.66608316e-18j,
                0.31313975 + 1.82190396e-01j,
                0.14075481 - 5.85637416e-02j,
                -0.15198775 - 1.02156797e-01j,
                0.38243133 - 6.66608316e-18j,
                0.3249317 + 1.47839074e-01j,
                0.14819172 - 3.78171168e-03j,
                -0.22808599 - 5.29338933e-02j,
                0.38243133 - 6.66608316e-18j,
                0.34595014 + 1.06355385e-01j,
                0.15519289 + 4.75602164e-02j,
                -0.22401193 - 4.33128746e-03j,
                0.38243133 - 6.66608316e-18j,
                0.36957165 + 5.69575709e-02j,
                0.17389327 + 5.53498385e-02j,
                -0.11601473 + 1.35405676e-02j,
                0.38243133 - 6.66608316e-18j,
                0.39045046 + 2.17911945e-03j,
                0.18146449 + 1.37089189e-02j,
                -0.02110144 - 6.65071497e-03j,
                0.38243133 - 6.66608316e-18j,
                0.4063995 - 5.21354967e-02j,
                0.15674204 - 3.85815662e-02j,
                -0.02886296 - 3.91489615e-02j,
                0.38243133 - 6.66608316e-18j,
                0.41872477 - 9.98946906e-02j,
                0.11862477 - 5.15231952e-02j,
                -0.05298751 - 1.95319478e-02j,
                0.38243133 - 6.66608316e-18j,
                0.43013599 - 1.38307796e-01j,
                0.10075763 - 1.25689289e-02j,
                -0.04052728 + 5.66863498e-02j,
                0.38243133 - 6.66608316e-18j,
                0.44144497 - 1.68826980e-01j,
                0.11446016 + 4.53003874e-02j,
                -0.03546515 + 1.13544145e-01j,
                0.38243133 - 6.66608316e-18j,
                0.44960099 - 1.94794929e-01j,
                0.15053714 + 8.11915305e-02j,
                -0.04800556 + 1.15828804e-01j,
                0.38243133 - 6.66608316e-18j,
                0.44872328 - 2.17957567e-01j,
                0.19116871 + 7.99536373e-02j,
                -0.05683092 + 9.72225058e-02j,
                0.38243133 - 6.66608316e-18j,
                0.43379428 - 2.36681249e-01j,
                0.21025378 + 5.48466438e-02j,
                -0.05318826 + 8.54948014e-02j,
                0.38243133 - 6.66608316e-18j,
                0.40485577 - 2.47073481e-01j,
                0.18680217 + 3.31766116e-02j,
                -0.06674163 + 7.94216591e-02j,
                0.38243133 - 6.66608316e-18j,
                0.36865853 - 2.45913767e-01j,
                0.13660805 + 3.68947359e-02j,
                -0.11467046 + 8.49198927e-02j,
                0.38243133 - 6.66608316e-18j,
                0.33597018 - 2.32971425e-01j,
                0.1072859 + 6.24686168e-02j,
                -0.12932565 + 1.06139634e-01j,
                0.38243133 - 6.66608316e-18j,
                0.31616666 - 2.10791785e-01j,
                0.11876919 + 7.93812474e-02j,
                -0.1094488 + 1.20159845e-01j,
                0.38243133 - 6.66608316e-18j,
                0.31313975 - 1.82190396e-01j,
                0.14075481 + 5.85637416e-02j,
                -0.15198775 + 1.02156797e-01j,
            ],
            dtype=complex_type(self.dtype),
        )
        self.assertTrue(np.allclose(pf, result))
Exemplo n.º 29
0
import numpy as np

from aspire.image import Image
from aspire.operators import CTFFilter

DATA_DIR = "data"
img_data = np.load(os.path.join(DATA_DIR, "monuments.npy"))
img_data.shape, img_data.dtype

# %%
# Create an Image Instance
# ------------------------

# Create an ASPIRE Image instance from the data
#   We'll tell it to convert to floating point data as well.
im = Image(img_data, dtype=np.float64)

# %%
# Plot the Image Stack
# --------------------

# Plot the Image stack
im.show()

# %%
# Apply a Uniform Shift
# ---------------------

# Apply a single shift to each image.
shifts = np.array([100, 30])
im.shift(shifts).show()
Exemplo n.º 30
0
# %%
# Review a class
# --------------
#
# Select a class to review.

review_class = 5

# Display the original image.
noisy_src.images(review_class, 1).show()

# Report the identified neighbor indices
logger.info(f"Class {review_class}'s neighors: {classes[review_class]}")

# Report the identified neighbors
Image(noisy_src.images(0, np.inf)[classes[review_class]]).show()

# Report their associated rots_refls
rots_refls = ["index, Rotation, Reflection"]
for i in range(classes.shape[1]):
    rots_refls.append(
        f"{i}, {rotations[review_class, i] * 180 / np.pi}, {reflections[review_class, i]}"
    )
rots_refls = "\n".join(rots_refls)

logger.info(
    f"Class {review_class}'s  estimated Rotations and Reflections:\n{rots_refls}"
)

# Display the averaged result
avgs.images(review_class, 1).show()