def rotateWeighting(weighting, z1, z2, x, mask=None, isReducedComplex=None, returnReducedComplex=False, binarize=False): """ rotateWeighting: Rotates a frequency weighting volume around the center. If the volume provided is reduced complex, it will be rescaled to full size, ftshifted, rotated, iftshifted and scaled back to reduced size. @param weighting: A weighting volume @type weighting: L{pytom_volume.vol} @param z1: Z1 rotation angle @type z1: float @param z2: Z2 rotation angle @type z2: float @param x: X rotation angle @type x: float @param mask:=None is there a rotation mask? A mask with all = 1 will be generated otherwise. Such mask should be \ provided anyway. @type mask: L{pytom_volume.vol} @param isReducedComplex: Either set to True or False. Will be determined otherwise @type isReducedComplex: bool @param returnReducedComplex: Return as reduced complex? (Default is False) @type returnReducedComplex: bool @param binarize: binarize weighting @type binarize: bool @return: weight as reduced complex volume @rtype: L{pytom_volume.vol_comp} """ from pytom_volume import vol, limit, vol_comp from pytom_volume import rotate assert type(weighting) == vol or type(weighting) == vol_comp, "rotateWeighting: input neither vol nor vol_comp" isReducedComplex = isReducedComplex or int(weighting.sizeX()/2)+1 == weighting.sizeZ(); if isReducedComplex: #scale weighting to full size from pytom_fftplan import fftShift from pytom_volume import reducedToFull weighting = reducedToFull(weighting) fftShift(weighting, True) if not mask: mask = vol(weighting.sizeX(),weighting.sizeY(),weighting.sizeZ()) mask.setAll(1) weightingRotated = vol(weighting.sizeX(),weighting.sizeY(),weighting.sizeZ()) rotate(weighting,weightingRotated,z1,z2,x) weightingRotated = weightingRotated * mask if returnReducedComplex: from pytom_fftplan import fftShift from pytom_volume import fullToReduced fftShift(weightingRotated,True) returnVolume = fullToReduced(weightingRotated) else: returnVolume = weightingRotated if binarize: limit(returnVolume,0.5,0,0.5,1,True,True) return returnVolume
def iftshift(data, inplace = True): """ iftshift: Performs a inverse fourier shift of data. Data must be full, the center is not determined accordingly. Assumes center is always size/2. @param data: - a volume @type data: pytom_volume.vol or pytom_volume.vol_comp @return: data inverse shifted @author: Thomas Hrabe """ import pytom_fftplan if inplace: pytom_fftplan.fftShift(data,True) return data else: from pytom_volume import vol, vol_comp if data.__class__ == vol: dummy = vol(data) elif data.__class__ == vol_comp: dummy = vol_comp(data) pytom_fftplan.fftShift(dummy,True) return dummy
def ftshift(data, inplace = True): """ ftshift: Performs a forward fourier shift of data. Data must be full, the center is not determined accordingly. Assumes center is always size/2. @param data: - a volume @type data: pytom_volume.vol or pytom_volume.vol_comp @param inplace: true by default @type inplace: boolean @return: data shifted @author: Thomas Hrabe """ import pytom_fftplan if inplace: pytom_fftplan.fftShift(data,False) return None else: from pytom_volume import vol, vol_comp if data.__class__ == vol: dummy = vol(data) elif data.__class__ == vol_comp: dummy = vol_comp(data) pytom_fftplan.fftShift(dummy,False) return dummy
def calculate_averages(pl, binning, mask, outdir='./'): """ calcuate averages for particle lists @param pl: particle list @type pl: L{pytom.basic.structures.ParticleList} @param binning: binning factor @type binning: C{int} last change: Jan 18 2020: error message for too few processes, FF """ import os from pytom_volume import complexDiv, vol, pasteCenter from pytom.basic.fourier import fft, ifft from pytom.basic.correlation import FSC, determineResolution from pytom_fftplan import fftShift from pytom_volume import reducedToFull pls = pl.copy().splitByClass() res = {} freqs = {} wedgeSum = {} for pp in pls: # ignore the -1 class, which is used for storing the trash class class_label = pp[0].getClass() if class_label != '-1': assert len(pp) > 3 if len(pp) >= 4 * mpi.size: spp = mpi._split_seq(pp, mpi.size) else: # not enough particle to do averaging on one node spp = [None] * 2 spp[0] = pp[:len(pp) // 2] spp[1] = pp[len(pp) // 2:] args = list( zip(spp, [True] * len(spp), [binning] * len(spp), [False] * len(spp), [outdir] * len(spp))) avgs = mpi.parfor(paverage, args) even_a, even_w, odd_a, odd_w = None, None, None, None even_avgs = avgs[1::2] odd_avgs = avgs[::2] for a, w in even_avgs: if even_a is None: even_a = a.getVolume() even_w = w.getVolume() else: even_a += a.getVolume() even_w += w.getVolume() os.remove(a.getFilename()) os.remove(w.getFilename()) for a, w in odd_avgs: if odd_a is None: odd_a = a.getVolume() odd_w = w.getVolume() else: odd_a += a.getVolume() odd_w += w.getVolume() os.remove(a.getFilename()) os.remove(w.getFilename()) # determine the resolution # raise error message in case even_a == None - only one processor used if even_a == None: from pytom.basic.exceptions import ParameterError raise ParameterError( 'cannot split odd / even. Likely you used only one processor - use: mpirun -np 2 (or higher!)?!' ) if mask and mask.__class__ == str: from pytom_volume import read, pasteCenter, vol maskBin = read(mask, 0, 0, 0, 0, 0, 0, 0, 0, 0, binning, binning, binning) if even_a.sizeX() != maskBin.sizeX() or even_a.sizeY( ) != maskBin.sizeY() or even_a.sizeZ() != maskBin.sizeZ(): mask = vol(even_a.sizeX(), even_a.sizeY(), even_a.sizeZ()) mask.setAll(0) pasteCenter(maskBin, mask) else: mask = maskBin fsc = FSC(even_a, odd_a, int(even_a.sizeX() // 2), mask) band = determineResolution(fsc, 0.5)[1] aa = even_a + odd_a ww = even_w + odd_w fa = fft(aa) r = complexDiv(fa, ww) rr = ifft(r) rr.shiftscale(0.0, 1. / (rr.sizeX() * rr.sizeY() * rr.sizeZ())) res[class_label] = rr freqs[class_label] = band ww2 = reducedToFull(ww) fftShift(ww2, True) wedgeSum[class_label] = ww2 print('done') return res, freqs, wedgeSum