Beispiel #1
0
    def covar_true(self):
        eigs_true, lamdbas_true = self.eigs()
        eigs_true = vol_to_vec(eigs_true)
        covar_true = eigs_true @ lamdbas_true @ eigs_true.T
        covar_true = vecmat_to_volmat(covar_true)

        return covar_true
Beispiel #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)
Beispiel #3
0
 def estimate(self, mean_vol, noise_variance, tol=None):
     logger.info('Running Covariance Estimator')
     b_coeff = self.src_backward(mean_vol, noise_variance)
     est_coeff = self.conj_grad(b_coeff, tol=tol)
     covar_est = self.basis.mat_evaluate(est_coeff)
     covar_est = vecmat_to_volmat(make_symmat(volmat_to_vecmat(covar_est)))
     return covar_est
Beispiel #4
0
    def compute_kernel(self):
        # TODO: Most of this stuff is duplicated in MeanEstimator - move up the hierarchy?
        n = self.n
        L = self.L
        _2L = 2 * self.L

        kernel = np.zeros((_2L, _2L, _2L, _2L, _2L, _2L), dtype=self.as_type)
        filters_f = self.src.filters.evaluate_grid(L)
        sq_filters_f = np.array(filters_f**2, dtype=self.as_type)

        for i in tqdm(range(0, n, self.batch_size)):
            pts_rot = rotated_grids(L, self.src.rots[:, :,
                                                     i:i + self.batch_size])
            weights = sq_filters_f[:, :,
                                   self.src.filters.indices[i:i +
                                                            self.batch_size]]
            weights *= self.src.amplitudes[i:i + self.batch_size]**2

            if L % 2 == 0:
                weights[0, :, :] = 0
                weights[:, 0, :] = 0

            # TODO: This is where this differs from MeanEstimator
            pts_rot = m_reshape(pts_rot, (3, L**2, -1))
            weights = m_reshape(weights, (L**2, -1))

            batch_n = weights.shape[-1]
            factors = np.zeros((_2L, _2L, _2L, batch_n), dtype=self.as_type)

            # TODO: Numpy has got to have a functional shortcut to avoid looping like this!
            for j in range(batch_n):
                factors[:, :, :, j] = anufft3(weights[:, j],
                                              pts_rot[:, :, j],
                                              (_2L, _2L, _2L),
                                              real=True)

            factors = vol_to_vec(factors)
            kernel += vecmat_to_volmat(factors @ factors.T) / (n * L**8)

        # Ensure symmetric kernel
        kernel[0, :, :, :, :, :] = 0
        kernel[:, 0, :, :, :, :] = 0
        kernel[:, :, 0, :, :, :] = 0
        kernel[:, :, :, 0, :, :] = 0
        kernel[:, :, :, :, 0, :] = 0
        kernel[:, :, :, :, :, 0] = 0

        logger.info('Computing non-centered Fourier Transform')
        kernel = mdim_ifftshift(kernel, range(0, 6))
        kernel_f = fftn(kernel)
        # Kernel is always symmetric in spatial domain and therefore real in Fourier
        kernel_f = np.real(kernel_f)

        return FourierKernel(kernel_f, centered=False)
Beispiel #5
0
    def toeplitz(self, L=None):
        """
        Compute the 3D Toeplitz matrix corresponding to this Fourier Kernel
        :param L: The size of the volumes to be convolved (default M/2, where the dimensions of this Fourier Kernel
            are MxMxM
        :return: An six-dimensional Toeplitz matrix of size L describing the convolution of a volume with this kernel
        """
        if L is None:
            L = int(self.M / 2)

        A = np.eye(L**3, dtype=self.as_type)
        for i in range(L**3):
            A[:, i] = vol_to_vec(self.convolve_volume(vec_to_vol(A[:, i])))

        A = vecmat_to_volmat(A)
        return A