def FLCF(volume, template, mask=None, stdV=None, gpu=False, mempool=None, pinned_mempool=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 ''' meanT = meanUnderMask(template, mask, gpu=gpu) temp = ((template - meanT) / stdUnderMask(template, mask, meanT, gpu=gpu)) * mask res = xp.fft.fftshift( xp.fft.ifftn(xp.conj(xp.fft.fftn(temp)) * xp.fft.fftn(volume))).real / stdV / mask.sum() meanT = None temp = None mempool.free_all_blocks() pinned_mempool.free_all_blocks()
def normalised_cross_correlation_mask(first, second, mask): """ Do cross correlation with a running mask based on numpy @param first: The first dataset (numpy 2D) @type first: numpy array 2D @param second: The second dataset (numpy 2D) @type second: numpy array 2D @param mask: The mask @type mask: numpy array 2D @return: The cross correlation result @returntype: numpy array 2D @requires: the shape of first to be equal to the shape of second and the shape of the mask """ # assert first.shape == second.shape # assert first.shape == mask.shape # assert len(first.shape) == 2 import xp.fft as nf a = norm_inside_mask(first, mask) b = norm_inside_mask(second, mask) return xp.real( nf.fftshift(nf.ifftn(xp.multiply(nf.fftn(b), xp.conj( nf.fftn(a)))))) / xp.sum(mask)
def normalised_cross_correlation(first, second, filter_mask=None, device=0): """ Do a cross correlation based on numpy @param first: The first dataset (numpy 2D) @type first: numpy array 2D @param second: The second dataset (numpy 2D) @type second: numpy array 2D @param filter_mask: a filter which is used to filter image 'first' @type filter_mask: numpy array 2D @return: The cross correlation result @returntype: numpy array 2D @requires: the shape of first to be equal to the shape of second, and equal t the shape of the filter (if used of course) """ assert first.shape == second.shape assert len(first.shape) == 2 if not (filter_mask is None): assert first.shape == filter_mask.shape # if filter_mask is None: ffirst = xp.fft.fft2(xp.array(first)) # else: # ffirst = xp.fft.fftshift(xp.fft.fftshift(xp.fft.fftn(first)) * filter_mask) ccmap = xp.real( xp.fft.fftshift( xp.fft.ifftn(xp.multiply(xp.fft.fftn(second), xp.conj(ffirst))))) / first.size return ccmap
def xcf( volume, template, mask=None, stdV=None, ): """ XCF: returns the non-normalised cross correlation function. The xcf result is scaled only by the square of the number of elements. @param volume : The search volume @type volume: L{pytom_volume.vol} @param template : The template searched (this one will be used for conjugate complex multiplication) @type template: L{pytom_volume.vol} @param mask: Will be unused, only for compatibility reasons with FLCF @param stdV: Will be unused, only for compatibility reasons with FLCF @return: XCF volume @rtype: L{pytom_volume.vol} @author: Thomas Hrabe """ # if mask: # volume = volume * mask # template = template * mask # determine fourier transforms of volumes if template.dtype in (xp.float64, xp.float32): fvolume = xp.fft.fftn(volume) else: fvolume = volume if template.dtype in (xp.float32, xp.float64): ftemplate = xp.fft.fftn(template) else: ftemplate = template # perform element wise - conjugate multiplication ftemplate = xp.conj(ftemplate) fresult = fvolume * ftemplate # transform back to real space result = abs(xp.fft.ifftn(fresult)) #xp.fft.iftshift(result) return result
def meanVolUnderMask(volume, mask): """ meanUnderMask: calculate the mean volume under the given mask (Both should have the same size) @param volume: input volume @type volume: L{numpy.ndarray} L{cupy.ndarray} @param mask: mask @type mask: L{numpy.ndarray} L{cupy.ndarray} @param p: non zero value numbers in the mask @type p: L{int} or L{float} @param gpu: Boolean that indicates if the input volumes stored on a gpu. @type gpu: L{bool} @return: the calculated mean volume under mask @rtype: L{numpy.ndarray} L{cupy.ndarray} @author: Gijs van der Schot """ res = xp.fft.fftshift( xp.fft.irfftn( xp.fft.rfftn(volume) * xp.conj(xp.fft.rfftn(mask)))) / mask.sum() return res.real
def meanVolUnderMaskPlanned(volume, mask, ifftnP, fftnP, plan): """ meanUnderMask: calculate the mean volume under the given mask (Both should have the same size) @param volume: input volume @type volume: L{numpy.ndarray} L{cupy.ndarray} @param mask: mask @type mask: L{numpy.ndarray} L{cupy.ndarray} @param p: non zero value numbers in the mask @type p: L{int} or L{float} @param gpu: Boolean that indicates if the input volumes stored on a gpu. @type gpu: L{bool} @return: the calculated mean volume under mask @rtype: L{numpy.ndarray} L{cupy.ndarray} @author: Gijs van der Schot """ volume_fft = fftnP(volume.astype(xp.complex64), plan=plan) mask_fft = fftnP(mask.astype(xp.complex64), plan=plan) res = xp.fft.fftshift(ifftnP(volume_fft * xp.conj(mask_fft), plan=plan)) / mask.sum() return res.real
def normalised_cross_correlation(first, second, filter_mask=None): """ Do a cross correlation based on numpy @param first: The first dataset (numpy 2D) @type first: numpy array 2D @param second: The second dataset (numpy 2D) @type second: numpy array 2D @param filter_mask: a filter which is used to filter image 'first' @type filter_mask: numpy array 2D @return: The cross correlation result @returntype: numpy array 2D @requires: the shape of first to be equal to the shape of second, and equal t the shape of the filter (if used of course) """ import sys from pytom.tompy.io import write assert first.shape == second.shape assert len(first.shape) == 2 if not (filter_mask is None): assert first.shape == filter_mask.shape from numpy.fft import fftshift, ifftn, fftn import numpy as xp prod = 1 for d in first.shape: prod *= d if filter_mask is None: ffirst = xp.fft.fftn(first) fsecond = xp.fft.fftn(second) else: ffirst = ((xp.fft.fftn(first)) * xp.fft.fftshift(filter_mask)) fsecond = xp.fft.fftn(second) * xp.fft.fftshift(filter_mask) ccmap = xp.real(xp.fft.fftshift(xp.fft.ifftn( fsecond * xp.conj(ffirst)))) / filter_mask.sum() # write('real_ccmap.mrc', ccmap) return ccmap
def fourier_reduced2full(data, isodd=False): """Return an Hermitian symmetried data. """ # get the original shape sx = data.shape[0] sy = data.shape[1] if isodd: sz = (data.shape[2] - 1) * 2 + 1 else: sz = (data.shape[2] - 1) * 2 res = xp.zeros((sx, sy, sz), dtype=data.dtype) res[:, :, 0:data.shape[2]] = data # calculate the coodinates accordingly szz = sz - data.shape[2] x, y, z = xp.indices((sx, sy, szz)) ind = [xp.mod(sx - x, sx), xp.mod(sy - y, sy), szz - z] # do the complex conjugate of the second part res[:, :, data.shape[2]:] = xp.conj(data[tuple(ind)]) return res
def bandCC(volume, reference, band, verbose=False, shared=None, index=None): """ bandCC: Determines the normalised correlation coefficient within a band @param volume: The volume @type volume: L{pytom_volume.vol} @param reference: The reference @type reference: L{pytom_volume.vol} @param band: [a,b] - specify the lower and upper end of band. @return: First parameter - The correlation of the two volumes in the specified band. Second parameter - The bandpass filter used. @rtype: List - [float,L{pytom_freqweight.weight}] @author: Thomas Hrabe """ if not index is None: print(index) from pytom.tompy.filter import bandpass from pytom.tompy.correlation import xcf #from pytom.tompy.filter import vol_comp if verbose: print('lowest freq : ', band[0], ' highest freq', band[1]) vf, m = bandpass(volume, band[0], band[1], returnMask=True, fourierOnly=True) rf = bandpass(reference, band[0], band[1], mask=m, fourierOnly=True) #,vf[1]) #ccVolume = vol_comp(rf[0].shape[0],rf[0].shape[1],rf[0].shape[2]) #ccVolume.copyVolume(rf[0]) vf = vf.astype(xp.complex128) ccVolume = rf.astype(vf.dtype) ccVolume = ccVolume * xp.conj(vf) #pytom_volume.conj_mult(ccVolume,vf[0]) cc = ccVolume.sum() cc = cc.real v = vf r = rf absV = xp.abs(v) absR = xp.abs(r) sumV = xp.sum(absV**2) sumR = xp.sum(absR**2) sumV = xp.abs(sumV) sumR = xp.abs(sumR) if sumV == 0: sumV = 1 if sumR == 0: sumR = 1 cc = cc / (xp.sqrt(sumV * sumR)) #numerical errors will be punished with nan if abs(cc) > 1.1: cc = float('nan') return float(cc)