Esempio n. 1
0
    def returnWedgeVolume(self, size, rotation=None):
        """Return the wedge volume in full size and zero in the center
        @param size: size of wedge
        @type size: C{list}
        @param rotation: rotation (3-dim vector if Euler angles)
        @type rotation: C{list}
        @return: wedge volume
        @rtype: Numpy array
        """
        assert len(size) == 3, "returnWedgeVolume: size must be 3-dim list"

        if self._volume is not None and np.array_equal(self._volume_shape,
                                                       size):
            pass
        else:
            self._create_wedge_volume(size)

        from pytom.tompy.transform import rotate3d, fourier_reduced2full, fftshift
        isodd = self._volume_shape[2] % 2
        wedge_vol = fftshift(fourier_reduced2full(self._volume, isodd))
        if rotation is not None:  # rotate the wedge first
            assert len(rotation) == 3
            wedge_vol = rotate3d(wedge_vol,
                                 rotation[0],
                                 rotation[1],
                                 rotation[2],
                                 order=1)

        return wedge_vol
Esempio n. 2
0
    def apply(self, data, rotation=None):
        """
        @param rotation: apply rotation to the wedge first
        """
        # if no missing wedge
        if self.start_ang == -90 and self.end_ang == 90:
            return data

        if self._volume is not None and np.array_equal(self._volume_shape,
                                                       data.shape):
            pass
        else:
            self._create_wedge_volume(data.shape)

        if rotation is not None:  # rotate the wedge first
            assert len(rotation) == 3
            from pytom.tompy.transform import rotate3d, fourier_reduced2full, fourier_full2reduced, fftshift, ifftshift
            isodd = self._volume_shape[2] % 2
            filter_vol = fftshift(fourier_reduced2full(self._volume, isodd))
            filter_vol = rotate3d(filter_vol,
                                  rotation[0],
                                  rotation[1],
                                  rotation[2],
                                  order=1)  # linear interp!
            filter_vol = fourier_full2reduced(ifftshift(filter_vol))
        else:
            filter_vol = self._volume

        from pytom.tompy.transform import fourier_filter
        res = fourier_filter(data, filter_vol, False)

        return res
Esempio n. 3
0
def FLCF(volume, template, mask=None, stdV=None):
    '''Fast local correlation function
    
    @param volume: target volume
    @param template: template to be searched. It can have smaller size then target volume.
    @param mask: template mask. If not given, a default sphere mask will be used.
    @param stdV: standard deviation of the target volume under mask, which do not need to be calculated again when the mask is identical.
    
    @return: the local correlation function
    '''
    if volume.shape[0] < template.shape[0] or volume.shape[1] < template.shape[
            1] or volume.shape[2] < template.shape[2]:
        raise Exception('Template size is bigger than the target volume!')

    # generate the mask
    if mask is None:
        from tools import create_sphere
        mask = create_sphere(template.shape)
    else:
        if template.shape[0] != mask.shape[0] and template.shape[
                1] != mask.shape[1] and template.shape[2] != mask.shape[2]:
            raise Exception('Template and mask sizes are not the same!')

    # normalize the template under mask
    meanT = mean_under_mask(template, mask)
    stdT = std_under_mask(template, mask, meanT)

    temp = (template - meanT) / stdT
    temp = temp * mask

    # construct both the template and the mask which has the same size as target volume
    from tools import paste_in_center
    tempV = temp
    if volume.shape[0] != temp.shape[0] or volume.shape[1] != temp.shape[
            1] or volume.shape[2] != temp.shape[2]:
        tempV = np.zeros(volume.shape)
        tempV = paste_in_center(temp, tempV)

    maskV = mask
    if volume.shape[0] != mask.shape[0] or volume.shape[1] != mask.shape[
            1] or volume.shape[2] != mask.shape[2]:
        maskV = np.zeros(volume.shape)
        maskV = paste_in_center(mask, maskV)

    # calculate the mean and std of volume
    meanV = mean_vol_under_mask(volume, maskV)
    stdV = std_vol_under_mask(volume, maskV, meanV)

    from transform import rfft, irfft, fftshift
    size = volume.shape
    fT = rfft(tempV)
    fT = np.conjugate(fT)
    result = fftshift(irfft(fT * rfft(volume), size)) / stdV

    return result / np.sum(mask)
Esempio n. 4
0
    def toSphericalFunc(self, bw, radius=None, threshold=0.5):
        """Convert the wedge from k-space to a spherical function. \
        currently some hard-coded parameters in - bw <=128, r=45 for max bw, default vol 100
        
        @param bw: bandwidth of the spherical function (must be <=128).
        @param radius: radius in k-space. For general Wedge, not used for SingleTiltWedge.
        @param threshold: threshold, above which the value there would be set to 1.

        @return: a spherical function in numpy.array - default 100x100x100 if no self.vol defined
        """
        assert (bw <= 128), "toSphericalFunc: bw currently limited to <= 128"

        # if no missing wedge
        if self.start_ang == -90 and self.end_ang == 90:
            self._sf = np.ones((4 * bw**2, ))
            return self._sf

        r = 45  # this radius and the volume size should be sufficient for sampling b <= 128
        if self._volume is None or np.min(self._volume.shape) < 100:
            self._create_wedge_volume((100, 100, 100))

        if self._bw == bw and self._sf is not None:
            return self._sf
        else:
            self._bw = bw

        from pytom.tompy.transform import fourier_reduced2full, fftshift
        isodd = self._volume_shape[2] % 2
        filter_vol = fftshift(fourier_reduced2full(self._volume, isodd))

        # start sampling
        from math import pi, sin, cos
        res = []

        for j in range(2 * bw):
            for k in range(2 * bw):
                the = pi * (2 * j + 1) / (4 * bw)  # (0,pi)
                phi = pi * k / bw  # [0,2*pi)

                # this part actually needs interpolation
                x = int(cos(phi) * sin(the) * r + 50)
                y = int(sin(phi) * sin(the) * r + 50)
                z = int(cos(the) * r + 50)

                # if the value is bigger than the threshold, we include it
                if filter_vol[x, y, z] > threshold:
                    res.append(1.0)
                else:
                    res.append(0.0)

        # store it so that we don't have to recompute it next time
        self._sf = np.array(res)

        return self._sf
Esempio n. 5
0
    def set_wedge_volume(self, wedge_vol, half=True, isodd=False):
        if half:
            self._volume = wedge_vol

            # human understandable version with 0-freq in the center
            from transform import fourier_reduced2full, fftshift
            self._whole_volume = fftshift(
                fourier_reduced2full(self._volume, isodd))
        else:
            self._whole_volume = wedge_vol

            from transform import fourier_full2reduced, ifftshift
            self._volume = fourier_full2reduced(ifftshift(self._whole_volume))
Esempio n. 6
0
def mean_vol_under_mask(volume, mask):
    """Calculate the mean volume under the mask (Both should have the same size).

    @param volume: input volume.
    @param mask: mask.
    
    @return: the calculated mean volume under mask.
    """
    p = np.sum(mask)

    # do the (circular) convolution
    from transform import rfft, irfft, fftshift
    size = volume.shape
    # somehow this should be conjugated
    res = fftshift(irfft(rfft(volume) * np.conjugate(rfft(mask)), size)) / p

    return res
Esempio n. 7
0
    def _create_wedge_volume(self, size):
        from transform import fftshift, fourier_full2reduced
        # if no missing wedge
        if self.start_ang == -90 and self.end_ang == 90:
            filter_vol = np.ones(size)
            self._volume = fourier_full2reduced(filter_vol)
            self._volume_shape = size
            return

        filter_vol = np.ones(size)
        x, z = scipy.mgrid[0.:size[0], 0.:size[2]]
        x -= size[0] / 2
        ind = np.where(x)  # find the non-zeros
        z -= size[2] / 2

        angles = np.zeros(z.shape)
        angles[ind] = np.arctan(z[ind] / x[ind]) * 180 / np.pi

        angles = np.reshape(angles, (size[0], 1, size[2]))
        angles = np.repeat(angles, size[1], axis=1)

        filter_vol[angles > -self.start_ang] = 0
        filter_vol[angles < -self.end_ang] = 0

        filter_vol[size[0] / 2, :, :] = 0
        filter_vol[size[0] / 2, :, size[2] / 2] = 1

        # create a sphere and multiple it with the wedge
        from tools import create_sphere
        mask = create_sphere(size)
        filter_vol *= mask

        # shift and cut in half
        filter_vol = fftshift(filter_vol)
        self._volume = fourier_full2reduced(filter_vol)

        self._volume_shape = size