def filter(volume,filterObject,fourierOnly=False): """ filter: A generic filter method. @param volume: The volume to be filtered @type volume: L{pytom_volume.vol} @type volume: L{pytom_volume.vol} @param filterObject: A filter object (either wedgeFilter, bandpassFilter, ...) @return: The filtered volume,the filter and the filtered volume in fourier space @author: Thomas Hrabe """ from pytom.basic.fourier import fft, ifft import pytom_volume if volume.__class__ == pytom_volume.vol: fvolume = fft(volume) noPixels = volume.sizeX() * volume.sizeY() * volume.sizeZ() else: fvolume = pytom_volume.vol_comp(volume.sizeX(),volume.sizeY(),volume.sizeZ()) fvolume.copyVolume(volume) if (volume.sizeZ() == 1) and (volume.sizeY() == 1): noPixels = 2 *(volume.sizeX()-1) elif volume.sizeZ() == 1: noPixels = volume.sizeX() *2 *(volume.sizeY()-1) else: noPixels = volume.sizeX() * volume.sizeY() * 2*(volume.sizeZ()-1) filterObject.apply(fvolume) if not fourierOnly: result = ifft(fvolume)/noPixels return [result,filterObject,fvolume] else: return [fvolume,filterObject]
def resize(volume, factor, interpolation='Fourier'): """ resize volume in real or Fourier space @param volume: input volume @type volume: L{pytom_volume.vol} @param factor: a factor > 0. Factors < 1 will de-magnify the volume, factors > 1 will magnify. @type factor: L{float} @param interpolation: Can be 'Fourier' (default), 'Spline', 'Cubic' or 'Linear' @type interpolation: L{str} @return: The re-sized volume @rtype: L{pytom_volume.vol} @author: FF """ if (interpolation == 'Spline') or (interpolation == 'Cubic') or (interpolation == 'Linear'): return scale(volume, factor, interpolation='Spline') else: from pytom.basic.fourier import fft, ifft fvol = fft(data=volume) newfvol = resizeFourier(fvol=fvol, factor=factor) newvol = ifft(newfvol) return newvol, newfvol
def convolutionCTF(volume, defocus, pixelSize=None, voltage=None, Cs=None, sigma=None): """ convolutionCTF: @param volume: input volume to be convolved with CTF @type volume: L{pytom_volume.vol} @param defocus: Negative value = underfocus (in microns) @param pixelSize: Size of pixels / voxels (in Anstroms) @param voltage: @param Cs: @param sigma: @return: CTF filtered volume @rtype L{pytom_volume.vol} @author: FF """ from pytom_volume import subvolume, complexRealMult from pytom.basic.fourier import ftshift, fft, ifft from pytom.basic.filter import volCTF dimX = volume.sizeX() dimY = volume.sizeY() dimZ = volume.sizeZ() ctf = volCTF(defocus, dimX, dimY, dimZ, pixelSize, voltage, Cs, sigma) filterCTF = subvolume(ftshift(ctf,inplace=False), 0, 0, 0, dimX, dimY, (dimZ/2)+1) filteredVolume = ifft( complexRealMult(fft(volume), filterCTF) ) return filteredVolume
def mean(volume, mask, fVolume=0, fMask=0, numberOfMaskVoxels=-1): """ suggestion frido: rename to mean_moving_mask mean: Determines the mean of volume under mask. Each assigned value is determined through the value of the voxels surrounding the current voxel that are covered by the mask. @param volume: The volume of interest @param mask: A mask under which the mean is determined @param fVolume: Optional - the fouriertransformed volume (fft must not be repeated) @param fMask: Optional - the fouriertransformed mask (fft must not be repeated) @param numberOfMaskVoxels: Optional - the number of voxels != 0 """ import pytom_volume if not fVolume.__class__ == pytom_volume.vol_comp: from pytom.basic.fourier import fft fVolume = fft(volume) if not fMask.__class__ == pytom_volume.vol_comp: from pytom.basic.fourier import fft fMask = fft(mask) if numberOfMaskVoxels < 0: numberOfMaskVoxels = pytom_volume.numberSetVoxels(mask) fMeanVol = fVolume * fMask from pytom.basic.fourier import ifft meanVolume = ifft(fMeanVol) from pytom.basic.fourier import iftshift iftshift(meanVolume) meanVolume.shiftscale(0, 1.0 / (numberOfMaskVoxels * meanVolume.numelem())) return meanVolume
def create_average(self, sum_ctf_conv, sum_ctf_squared, wedge_weight): """For the master node, this function is rewritten. """ from pytom_volume import vol, complexDiv, fullToReduced, initSphere, complexRealMult, limit from pytom.basic.fourier import fft, ifft, ftshift from pytom.basic.normalise import mean0std1 # limit(wedge_weight, 0.1, 0, 0,0,True,False) # set all the values below the specified value to 0 # for mask out the outside area # mask = vol(sum_ctf_conv) # mask.setAll(0) # initSphere(mask, sum_ctf_conv.sizeX()/2-1, 0,0, sum_ctf_conv.sizeX()/2, sum_ctf_conv.sizeX()/2, sum_ctf_conv.sizeX()/2) # mask = fullToReduced(ftshift(mask, inplace=False)) # Wiener filter numerator = fft(sum_ctf_conv) sum_ctf_squared = fullToReduced(ftshift(sum_ctf_squared, inplace=False)) denominator = (sum_ctf_squared+1)*wedge_weight r = complexDiv(numerator, denominator) # average = ifft(complexRealMult(r, mask)) average = ifft(r) average.shiftscale(0.0,1/float(average.sizeX()*average.sizeY()*average.sizeZ())) # nomalize the average try: average = mean0std1(average, True) except: average *= 1000 # in case the average volume is too small to normalize average = mean0std1(average, True) return average
def bandCF(volume, reference, band=[0, 100]): """ bandCF: @param volume: The volume @param reference: The reference @param band: [a,b] - specify the lower and upper end of band. [0,1] if not set. @return: First parameter - The correlation of the two volumes in the specified ring. Second parameter - The bandpass filter used. @rtype: List - [L{pytom_volume.vol},L{pytom_freqweight.weight}] @author: Thomas Hrabe @todo: does not work yet -> test is disabled """ if gpu: import cupy as xp else: import numpy as xp import pytom_volume from math import sqrt from pytom.basic import fourier from pytom.basic.filter import bandpassFilter from pytom.basic.correlation import nXcf vf = bandpassFilter(volume, band[0], band[1], fourierOnly=True) rf = bandpassFilter(reference, band[0], band[1], vf[1], fourierOnly=True) v = pytom_volume.reducedToFull(vf[0]) r = pytom_volume.reducedToFull(rf[0]) absV = pytom_volume.abs(v) absR = pytom_volume.abs(r) pytom_volume.power(absV, 2) pytom_volume.power(absR, 2) sumV = abs(pytom_volume.sum(absV)) sumR = abs(pytom_volume.sum(absR)) if sumV == 0: sumV = 1 if sumR == 0: sumR = 1 pytom_volume.conjugate(rf[0]) fresult = vf[0] * rf[0] #transform back to real space result = fourier.ifft(fresult) fourier.iftshift(result) result.shiftscale(0, 1 / float(sqrt(sumV * sumR))) return [result, vf[1]]
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: changed: will be used if specified @type mask: L{pytom_volume.vol} @param stdV: Will be unused, only for compatibility reasons with FLCF @return: XCF volume @rtype: L{pytom_volume.vol} @author: Thomas Hrabe """ import pytom_volume from pytom.basic import fourier if mask != None: volume = volume * mask template = template * mask #determine fourier transforms of volumes if volume.__class__ == pytom_volume.vol: from pytom.basic.fourier import fft fvolume = fft(volume) else: fvolume = volume if template.__class__ == pytom_volume.vol: from pytom.basic.fourier import fft ftemplate = fft(template) else: ftemplate = template #perform element wise - conjugate multiplication pytom_volume.conjugate(ftemplate) fresult = fvolume * ftemplate #transform back to real space result = fourier.ifft(fresult) fourier.iftshift(result) n = result.numelem() if mask: n1 = pytom_volume.sum(mask) # real -> FFT requires n1, FFT -> real n result.shiftscale(0,1/float(n1*n)) else: result.shiftscale(0,1/float(n*n)) return result
def fourier_rotate(v, phi, psi, the): vf = ftshift(reducedToFull(fft(iftshift(v, inplace=False))), inplace=False) vfr = real(vf) vfi = imag(vf) rr = vol(vfr) ii = vol(vfi) rotateSpline(vfr, rr, phi, psi, the) rotateSpline(vfi, ii, phi, psi, the) # print vfr(12,12,12),rr(12,12,12) vv = mergeRealImag(rr, ii) return ftshift(ifft(fullToReduced(iftshift(vv, inplace=False))), inplace=False) / v.numelem()
def create_average(self, pre, wedge): """For the master node, create the average according to the pre-wedge and wedge volumes. """ from pytom_volume import complexDiv, limit from pytom.basic.fourier import fft, ifft limit(wedge, 0.1, 0, 0, 0, True, False) # set all the values below the specified value to 0 f_pre = fft(pre) r = complexDiv(f_pre, wedge) average = ifft(r) average.shiftscale( 0.0, 1 / float(average.sizeX() * average.sizeY() * average.sizeZ())) return average
def shift(volume,shiftX,shiftY,shiftZ,imethod='fourier',twice=False): """ shift: Performs a shift on a volume @param volume: the volume @param shiftX: shift in x direction @param shiftY: shift in y direction @param shiftZ: shift in z direction @param imethod: Select interpolation method. Real space : linear, cubic, spline . Fourier space: fourier @param twice: Zero pad volume into a twice sized volume and perform calculation there. @return: The shifted volume. @author: Yuxiang Chen and Thomas Hrabe """ if imethod == 'fourier': from pytom_volume import vol_comp,reducedToFull,fullToReduced,shiftFourier from pytom.basic.fourier import fft,ifft,ftshift, iftshift fvolume = fft(volume) fullFVolume = reducedToFull(fvolume) destFourier = vol_comp(fullFVolume.sizeX(),fullFVolume.sizeY(),fullFVolume.sizeZ()) shiftFourier(fullFVolume,destFourier,shiftX,shiftY,shiftZ) resFourier = fullToReduced(destFourier) return ifft(resFourier)/volume.numelem() else: from pytom_volume import vol if imethod == 'linear': from pytom_volume import transform elif imethod == 'cubic': from pytom_volume import transformCubic as transform elif imethod == 'spline': from pytom_volume import transformSpline as transform # now results should be consistent with python2 centerX = int(volume.sizeX()/2) centerY = int(volume.sizeY()/2) centerZ = int(volume.sizeZ()/2) res = vol(volume.sizeX(),volume.sizeY(),volume.sizeZ()) transform(volume,res,0,0,0,centerX,centerY,centerZ,shiftX,shiftY,shiftZ,0,0,0) return res
def mean0std1(volume, copyFlag=False): """ mean0std1: normalises input volume to mean 0 and std 1. Procedure is performed inplace if copyFlag is unspecified!!! @param volume: Data containing either an image or a volume @param copyFlag: If True a copy of volume will be returned. False unless specified otherwise. @return: If copyFlag == True, then return a normalised copy. @author: Thomas Hrabe """ import pytom_volume from math import sqrt from pytom.tools.maths import epsilon if volume.__class__ == pytom_volume.vol_comp: from pytom.basic.fourier import ifft, iftshift volume = iftshift(ifft(volume)) if not copyFlag: volumeMean = pytom_volume.mean(volume) volume.shiftscale(-volumeMean, 1) volumeStd = sqrt(pytom_volume.variance(volume, False)) if volumeStd < epsilon: raise ValueError( 'pytom_normalise.mean0std1 : The standard deviation is too low for division! ' + str(volumeStd)) volume.shiftscale(0, 1. / float(volumeStd)) else: volumeCopy = pytom_volume.vol(volume.sizeX(), volume.sizeY(), volume.sizeZ()) volumeCopy.copyVolume(volume) volumeMean = pytom_volume.mean(volumeCopy) volumeCopy.shiftscale(-1. * volumeMean, 1) volumeStd = sqrt(pytom_volume.variance(volumeCopy, False)) if volumeStd < epsilon: raise ValueError( 'pytom_normalise.mean0std1 : The standard deviation is too low for division! ' + str(volumeStd)) #volumeCopy.shiftscale(-1.*volumeMean,1) volumeCopy.shiftscale(0, 1 / float(volumeStd)) return volumeCopy
def getWeightedProjectionCube(sourceVolume, thetaAngles): from pytom_volume import vol, paste from pytom_volume import complexRealMult from pytom.basic.fourier import fft from pytom.basic.fourier import ifft from pytom.basic.filter import fourierFilterShift from pytom.basic.filter import circleFilter from pytom.basic.filter import rampFilter dimX = sourceVolume.sizeX() dimY = sourceVolume.sizeY() imageCube = vol(dimX, dimY, len(thetaAngles)) imageCube.setAll(0.0) weightSlice = fourierFilterShift(rampFilter(sourceVolume)) circleFilterRadius = dimX / 2 circleSlice = fourierFilterShift( circleFilter(sourceVolume, circleFilterRadius)) for k in range(len(thetaAngles)): angle = thetaAngles[k] image = theta_vol_projection(sourceVolume, angle) ##filtered_img = ifft( complexRealMult(complexRealMult(complexRealMult(fft(image), filter_slice), circle_filter_slice), ctf) ) filteredImage = ifft( complexRealMult(complexRealMult(fft(image), weightSlice), circleSlice)) paste(filteredImage, imageCube, 0, 0, k) #for i in range(dimX): # for j in range(dimY): # imageCube.setV(filteredImage.getV(i, j, 0), i, j, k) return imageCube
def std(volume, mask, meanVolume=0, fMask=0, numberOfMaskVoxels=-1): """ suggestion frido: rename to std_moving_mask std: Determines the std of volume under moving mask. Each assigned value is determined through the value of the voxels surrounding the current voxel that are covered by the mask. @param volume: The volume of interest @param mask: A mask under which the std is determined @param meanVolume: Optional - the meanVolume determined by mean. (mean must not be recalculated) @param fMask: Optional - the fouriertransformed mask (fft must not be repeated) @param numberOfMaskVoxels: Optional - the number of voxels != 0 """ from pytom.basic.fourier import fft, ifft, iftshift from pytom_volume import power import pytom_volume if not fMask.__class__ == pytom_volume.vol_comp: fMask = fft(mask) if not meanVolume.__class__ == pytom_volume.vol: meanVolume = mean(volume, mask) if numberOfMaskVoxels < 0: numberOfMaskVoxels = pytom_volume.numberSetVoxels(mask) volumeSqrd = volume * volume fVolumeSqrd = fft(volumeSqrd) fVolumeSqrd = fVolumeSqrd * fMask varianceVolume = iftshift(ifft(fVolumeSqrd)) varianceVolume.shiftscale( 0, 1.0 / (numberOfMaskVoxels * varianceVolume.numelem())) power(meanVolume, 2) varianceVolume = varianceVolume - meanVolume power(varianceVolume, 0.5) return varianceVolume
def transformFourierSpline(volume,z1,z2,x,shiftX,shiftY,shiftZ,twice=False): """ transformFourierSpline: Rotate and shift a volume in fourierspace @param volume: @param z1: @param z2: @param x: @param shiftX: Shift after rotation @param shiftY: Shift after rotation @param shiftZ: Shift after rotation @param twice: Zero pad volume into a twice sized volume and perform calculation there. @return: The transformed volume. @author: Yuxiang Chen and Thomas Hrabe """ from pytom.basic.fourier import fft, ifft, ftshift, iftshift from pytom_volume import vol, pasteCenter, subvolume, transformFourierSpline if z1 == 0 and z2 == 0 and x == 0: return vol(volume) if twice: # paste into a twice sized volume v = vol(volume.sizeX()*2, volume.sizeY()*2, volume.sizeZ()*2) pasteCenter(volume, v) else: v = volume fvol = fft(iftshift(v, inplace=False)) # these steps have to be done in python level because of the fft resF = transformFourierSpline(fvol,z1,z2,x,shiftX,shiftY,shiftZ) res = ftshift(ifft(resF),inplace=False) / v.numelem() # reverse it back if twice: # cut the center part back res = subvolume(res, (volume.sizeX()+1)/2, (volume.sizeY()+1)/2, (volume.sizeZ()+1)/2, volume.sizeX(), volume.sizeY(), volume.sizeZ()) return res
def create_average(self, pre, wedge): """For the master node, create the average according to the pre-wedge and wedge volumes. @param pre: density prior to weighting @type pre: L{pytom_volume.vol} @param wedge: wedge @type wedge: L{pytom.basic.Wedge} @return: wedge-weighted density @rtype: L{pytom_volume.vol} """ from pytom_volume import complexDiv, limit from pytom.basic.fourier import fft, ifft limit(wedge, 0.1, 0, 0, 0, True, False) # set all the values below the specified value to 0 f_pre = fft(pre) r = complexDiv(f_pre, wedge) average = ifft(r) average.shiftscale( 0.0, 1 / float(average.sizeX() * average.sizeY() * average.sizeZ())) return average
def meanUnderMask(volume, mask, p): """ meanUnderMask: calculate the mean volume under the given mask (Both should have the same size) @param volume: input volume @type volume: L{pytom_volume.vol} @param mask: mask @type mask: L{pytom_volume.vol} @param p: non zero value numbers in the mask @type p: L{int} or L{float} @return: the calculated mean volume under mask @rtype: L{pytom_volume.vol} @author: Yuxiang Chen """ size = volume.numelem() from pytom.basic.fourier import fft, ifft, iftshift from pytom_volume import conjugate # for some reason, this has to be conjugated. (Otherwise the asym mask won't work) fMask = fft(mask) conjugate(fMask) result = iftshift(ifft(fMask*fft(volume)))/(size*p) return result
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
def average2(particleList, weighting=False, norm=False, determine_resolution=False, mask=None, binning=1, verbose=False): """ 2nd version of average function. Will not write the averages to the disk. Also support internal \ resolution determination. """ from pytom_volume import read, vol, complexDiv, complexRealMult from pytom_volume import transformSpline as transform from pytom.basic.fourier import fft, ifft, convolute from pytom.basic.normalise import mean0std1 from pytom.tools.ProgressBar import FixedProgBar from pytom.basic.filter import lowpassFilter, rotateWeighting from math import exp if len(particleList) == 0: raise RuntimeError('The particlelist provided is empty. Aborting!') if verbose: progressBar = FixedProgBar(0,len(particleList),'Particles averaged ') progressBar.update(0) numberAlignedParticles = 0 even = None odd = None wedgeSum_even = None wedgeSum_odd = None newParticle = None is_odd = True for particleObject in particleList: particle = read(particleObject.getFilename(), 0,0,0,0,0,0,0,0,0, binning,binning,binning) if norm: mean0std1(particle) wedgeInfo = particleObject.getWedge() # apply its wedge to itself particle = wedgeInfo.apply(particle) if odd is None: # initialization sizeX = particle.sizeX() sizeY = particle.sizeY() sizeZ = particle.sizeZ() newParticle = vol(sizeX,sizeY,sizeZ) centerX = sizeX/2 centerY = sizeY/2 centerZ = sizeZ/2 odd = vol(sizeX,sizeY,sizeZ) odd.setAll(0.0) even = vol(sizeX,sizeY,sizeZ) even.setAll(0.0) wedgeSum_odd = wedgeInfo.returnWedgeVolume(sizeX,sizeY,sizeZ) wedgeSum_odd.setAll(0) wedgeSum_even = wedgeInfo.returnWedgeVolume(sizeX,sizeY,sizeZ) wedgeSum_even.setAll(0) # create spectral wedge weighting rotation = particleObject.getRotation() rotinvert = rotation.invert() if analytWedge: # > original buggy version wedge = wedgeInfo.returnWedgeVolume(sizeX,sizeY,sizeZ,False, rotinvert) # < original buggy version else: # > FF: interpol bugfix wedge = rotateWeighting( weighting=wedgeInfo.returnWedgeVolume(sizeX,sizeY,sizeZ,False), z1=rotinvert[0], z2=rotinvert[1], x=rotinvert[2], mask=None, isReducedComplex=True, returnReducedComplex=True) # < FF # > TH bugfix #wedgeVolume = wedgeInfo.returnWedgeVolume(wedgeSizeX=sizeX, wedgeSizeY=sizeY, wedgeSizeZ=sizeZ, # humanUnderstandable=True, rotation=rotinvert) #wedge = rotate(volume=wedgeVolume, rotation=rotinvert, imethod='linear') # < TH if is_odd: wedgeSum_odd = wedgeSum_odd + wedge else: wedgeSum_even = wedgeSum_even + wedge # shift and rotate particle shiftV = particleObject.getShift() newParticle.setAll(0) transform(particle,newParticle,-rotation[1],-rotation[0],-rotation[2], centerX,centerY,centerZ,-shiftV[0]/binning, -shiftV[1]/binning,-shiftV[2]/binning,0,0,0) if is_odd: if weighting: weight = 1. - particleObject.getScore().getValue() #weight = weight**2 weight = exp(-1.*weight) odd = odd + newParticle * weight else: odd = odd + newParticle else: if weighting: weight = 1. - particleObject.getScore().getValue() #weight = weight**2 weight = exp(-1.*weight) even = even + newParticle * weight else: even = even + newParticle is_odd = not is_odd if verbose: numberAlignedParticles = numberAlignedParticles + 1 progressBar.update(numberAlignedParticles) # determine resolution if needed fsc = None if determine_resolution: # apply spectral weighting to sum f_even = fft(even) w_even = complexDiv(f_even, wedgeSum_even) w_even = ifft(w_even) w_even.shiftscale(0.0,1/float(sizeX*sizeY*sizeZ)) f_odd = fft(odd) w_odd = complexDiv(f_odd, wedgeSum_odd) w_odd = ifft(w_odd) w_odd.shiftscale(0.0,1/float(sizeX*sizeY*sizeZ)) from pytom.basic.correlation import FSC fsc = FSC(w_even, w_odd, sizeX/2, mask, verbose=False) # add together result = even+odd wedgeSum = wedgeSum_even+wedgeSum_odd invert_WedgeSum( invol=wedgeSum, r_max=sizeX/2-2., lowlimit=.05*len(particleList), lowval=.05*len(particleList)) #wedgeSum.write(averageName[:len(averageName)-3] + '-WedgeSumInverted.em') result = convolute(v=result, k=wedgeSum, kernel_in_fourier=True) # do a low pass filter #result = lowpassFilter(result, sizeX/2-2, (sizeX/2-1)/10.)[0] return (result, fsc)
def _disrtibuteAverageMPI(particleList,averageName,showProgressBar = False,verbose=False, createInfoVolumes = False,setParticleNodesRatio = 3,sendEndMessage = False): """ _distributeAverageMPI : Distributes averaging to multiple MPI nodes. @param particleList: The particles @param averageName: Filename of new average @param verbose: Prints particle information. Disabled by default. @param createInfoVolumes: Create info data (wedge sum, inverted density) too? False by default. @return: A new Reference object @rtype: L{pytom.basic.structures.Reference} @author: Thomas Hrabe """ import pytom_mpi from pytom.alignment.structures import ExpectationJob from pytom.parallel.parallelWorker import ParallelWorker from pytom.parallel.alignmentMessages import ExpectationJobMsg from pytom_volume import read,complexDiv,complexRealMult from pytom.basic.fourier import fft,ifft from pytom.basic.filter import lowpassFilter from pytom.basic.structures import Reference import os import sys numberOfNodes = pytom_mpi.size() particleNodesRatio = float(len(particleList)) / float(numberOfNodes) splitFactor = numberOfNodes if particleNodesRatio < setParticleNodesRatio: #make sure each node gets at least 20 particles. splitFactor = len(particleList) / setParticleNodesRatio splitLists = particleList.splitNSublists(splitFactor) msgList = [] avgNameList = [] preList = [] wedgeList = [] for i in range(len(splitLists)): plist = splitLists[i] avgName = averageName + '_dist' +str(i) + '.em' avgNameList.append(avgName) preList.append(averageName + '_dist' +str(i) + '-PreWedge.em') wedgeList.append(averageName + '_dist' +str(i) + '-WedgeSumUnscaled.em') job = ExpectationJob(plist,avgName) message = ExpectationJobMsg(0,i) message.setJob(job) msgList.append(message) #distribute averaging worker = ParallelWorker() worker.fillJobList(msgList) worker.parallelWork(True,sendEndMessage) #collect results result = read(preList[0]) wedgeSum = read(wedgeList[0]) for i in range(1,len(preList)): r = read(preList[i]) result += r w = read(wedgeList[i]) wedgeSum += w result.write(averageName[:len(averageName)-3]+'-PreWedge.em') wedgeSum.write(averageName[:len(averageName)-3] + '-WedgeSumUnscaled.em') invert_WedgeSum( invol=wedgeSum, r_max=result.sizeX()/2-2., lowlimit=.05*len(particleList), lowval=.05*len(particleList)) fResult = fft(result) r = complexRealMult(fResult,wedgeSum) result = ifft(r) result.shiftscale(0.0,1/float(result.sizeX()*result.sizeY()*result.sizeZ())) # do a low pass filter result = lowpassFilter(result, result.sizeX()/2-2, (result.sizeX()/2-1)/10.)[0] result.write(averageName) # clean results for i in range(0,len(preList)): os.system('rm ' + avgNameList[i]) os.system('rm ' + preList[i]) os.system('rm ' + wedgeList[i]) return Reference(averageName,particleList)
def writeAlignedProjections(TiltSeries_, weighting=None, lowpassFilter=None, binning=None, verbose=False, write_images=True): """write weighted and aligned projections to disk1 @param TiltSeries_: Tilt Series @type TiltSeries_: reconstruction.TiltSeries @param weighting: weighting (<0: analytical weighting, >1 exact weighting (value corresponds to object diameter in pixel AFTER binning) @type weighting: float @param lowpassFilter: lowpass filter (in Nyquist) @type lowpassFilter: float @param binning: binning (default: 1 = no binning). binning=2: 2x2 pixels -> 1 pixel, binning=3: 3x3 pixels -> 1 pixel, etc. @author: FF """ import numpy from pytom_numpy import vol2npy from pytom.basic.files import read_em, write_em from pytom.basic.functions import taper_edges from pytom.basic.transformations import general_transform2d from pytom.basic.fourier import ifft, fft from pytom.basic.filter import filter as filterFunction, bandpassFilter from pytom.basic.filter import circleFilter, rampFilter, exactFilter, fourierFilterShift, rotateFilter from pytom_volume import complexRealMult, vol import pytom_freqweight from pytom.basic.transformations import resize from pytom.gui.guiFunctions import fmtAR, headerAlignmentResults, datatypeAR import os if binning: imdim = int(float(TiltSeries_._imdim) / float(binning) + .5) else: imdim = TiltSeries_._imdim print('imdim', imdim) sliceWidth = imdim # pre-determine analytical weighting function and lowpass for speedup if (weighting != None) and (weighting < -0.001): w_func = fourierFilterShift(rampFilter(imdim, imdim)) print('start weighting') # design lowpass filter if lowpassFilter: if lowpassFilter > 1.: lowpassFilter = 1. print("Warning: lowpassFilter > 1 - set to 1 (=Nyquist)") # weighting filter: arguments: (angle, cutoff radius, dimx, dimy, lpf = pytom_freqweight.weight(0.0, lowpassFilter * imdim / 2, imdim, imdim // 2 + 1, 1, lowpassFilter / 5. * imdim) #lpf = bandpassFilter(volume=vol(imdim, imdim,1),lowestFrequency=0,highestFrequency=int(lowpassFilter*imdim/2), # bpf=None,smooth=lowpassFilter/5.*imdim,fourierOnly=False)[1] tilt_angles = [] for projection in TiltSeries_._ProjectionList: tilt_angles.append(projection._tiltAngle) tilt_angles = sorted(tilt_angles) print(tilt_angles) #q = numpy.matrix(abs(numpy.arange(-imdim//2, imdim//2))) alignmentResults = numpy.zeros((len(TiltSeries_._ProjectionList)), dtype=datatypeAR) alignmentResults['TiltAngle'] = tilt_angles for (ii, projection) in enumerate(TiltSeries_._ProjectionList): alignmentResults['FileName'][ii] = os.path.join( os.getcwd(), projection._filename) transX = -projection._alignmentTransX / binning transY = -projection._alignmentTransY / binning rot = -(projection._alignmentRotation + 90.) mag = projection._alignmentMagnification alignmentResults['AlignmentTransX'][ii] = transX alignmentResults['AlignmentTransY'][ii] = transY alignmentResults['InPlaneRotation'][ii] = rot alignmentResults['Magnification'][ii] = mag if write_images: if projection._filename.split('.')[-1] == 'st': from pytom.basic.files import EMHeader, read header = EMHeader() header.set_dim(x=imdim, y=imdim, z=1) idx = projection._index if verbose: print("reading in projection %d" % idx) image = read(file=projection._filename, subregion=[ 0, 0, idx - 1, TiltSeries_._imdim, TiltSeries_._imdim, 1 ], sampling=[0, 0, 0], binning=[0, 0, 0]) if not (binning == 1) or (binning == None): image = resize(volume=image, factor=1 / float(binning))[0] else: # read projection files from pytom.basic.files import EMHeader, read, read_em_header print(projection._filename) image = read(projection._filename) image = resize(volume=image, factor=1 / float(binning))[0] if projection._filename[-3:] == '.em': header = read_em_header(projection._filename) else: header = EMHeader() header.set_dim(x=imdim, y=imdim, z=1) if lowpassFilter: filtered = filterFunction(volume=image, filterObject=lpf, fourierOnly=False) image = filtered[0] tiltAngle = projection._tiltAngle header.set_tiltangle(tiltAngle) # normalize to contrast - subtract mean and norm to mean immean = vol2npy(image).mean() image = (image - immean) / immean # smoothen borders to prevent high contrast oscillations image = taper_edges(image, imdim // 30)[0] # transform projection according to tilt alignment if projection._filename.split('.')[-1] == 'st': newFilename = (TiltSeries_._alignedTiltSeriesName + "_" + str(projection.getIndex()) + '.em') else: TiltSeries_._tiltSeriesFormat = 'mrc' newFilename = (TiltSeries_._alignedTiltSeriesName + "_" + str(projection.getIndex()) + '.' + TiltSeries_._tiltSeriesFormat) if verbose: tline = ("%30s" % newFilename) tline = tline + (" (tiltAngle=%6.2f)" % tiltAngle) tline = tline + (": transX=%6.1f" % transX) tline = tline + (", transY=%6.1f" % transY) tline = tline + (", rot=%6.2f" % rot) tline = tline + (", mag=%5.4f" % mag) print(tline) image = general_transform2d(v=image, rot=rot, shift=[transX, transY], scale=mag, order=[2, 1, 0], crop=True) # smoothen once more to avoid edges image = taper_edges(image, imdim // 30)[0] # analytical weighting if (weighting != None) and (weighting < 0): image = (ifft(complexRealMult(fft(image), w_func)) / (image.sizeX() * image.sizeY() * image.sizeZ())) elif (weighting != None) and (weighting > 0): if abs(weighting - 2) < 0.001: w_func = fourierFilterShift( rotateFilter(tilt_angles, tiltAngle, imdim, imdim, sliceWidth)) else: w_func = fourierFilterShift( exactFilter(tilt_angles, tiltAngle, imdim, imdim, sliceWidth)) image = (ifft(complexRealMult(fft(image), w_func)) / (image.sizeX() * image.sizeY() * image.sizeZ())) header.set_tiltangle(tilt_angles[ii]) if newFilename.endswith('.mrc'): data = copy.deepcopy(vol2npy(image)) mrcfile.new(newFilename, data.T.astype(float32), overwrite=True) else: write_em(filename=newFilename, data=image, header=header) if verbose: tline = ("%30s written ..." % newFilename) outname = os.path.join(os.path.dirname(TiltSeries_._alignedTiltSeriesName), 'alignmentResults.txt') numpy.savetxt(outname, alignmentResults, fmt=fmtAR, header=headerAlignmentResults) print('Alignment successful. See {} for results.'.format(outname))
def averageParallel(particleList, averageName, showProgressBar=False, verbose=False, createInfoVolumes=False, weighting=None, norm=False, setParticleNodesRatio=3, cores=6): """ compute average using parfor @param particleList: The particles @param averageName: Filename of new average @param verbose: Prints particle information. Disabled by default. @param createInfoVolumes: Create info data (wedge sum, inverted density) too? False by default. @param weighting: weight particles by exp CC in average @type weighting: bool @param setParticleNodesRatio: minimum number of particles per node @type setParticleNodesRatio: L{int} @return: A new Reference object @rtype: L{pytom.basic.structures.Reference} @author: FF """ from pytom_volume import read, complexRealMult from pytom.basic.fourier import fft, ifft from pytom.basic.filter import lowpassFilter from pytom.basic.structures import Reference from pytom.alignment.alignmentFunctions import invert_WedgeSum import os splitLists = splitParticleList(particleList, setParticleNodesRatio=setParticleNodesRatio, numberOfNodes=cores) splitFactor = len(splitLists) avgNameList = [] preList = [] wedgeList = [] for ii in range(splitFactor): avgName = averageName + '_dist' + str(ii) + '.em' avgNameList.append(avgName) preList.append(averageName + '_dist' + str(ii) + '-PreWedge.em') wedgeList.append(averageName + '_dist' + str(ii) + '-WedgeSumUnscaled.em') #reference = average(particleList=plist, averageName=xxx, showProgressBar=True, verbose=False, # createInfoVolumes=False, weighting=weighting, norm=False) from multiprocessing import Process procs = [] for i in range(splitFactor): proc = Process(target=average, args=(splitLists[i], avgNameList[i], showProgressBar, verbose, createInfoVolumes, weighting, norm)) procs.append(proc) proc.start() import time while procs: procs = [proc for proc in procs if proc.is_alive()] time.sleep(.1) #averageList = mpi.parfor( average, list(zip(splitLists, avgNameList, [showProgressBar]*splitFactor, # [verbose]*splitFactor, [createInfoVolumes]*splitFactor, # [weighting]*splitFactor, [norm]*splitFactor)), verbose=True) #collect results from files unweiAv = read(preList[0]) wedgeSum = read(wedgeList[0]) os.system('rm ' + wedgeList[0]) os.system('rm ' + avgNameList[0]) os.system('rm ' + preList[0]) for ii in range(1, splitFactor): av = read(preList[ii]) unweiAv += av os.system('rm ' + preList[ii]) w = read(wedgeList[ii]) wedgeSum += w os.system('rm ' + wedgeList[ii]) os.system('rm ' + avgNameList[ii]) if createInfoVolumes: unweiAv.write(averageName[:len(averageName) - 3] + '-PreWedge.em') wedgeSum.write(averageName[:len(averageName) - 3] + '-WedgeSumUnscaled.em') # convolute unweighted average with inverse of wedge sum invert_WedgeSum(invol=wedgeSum, r_max=unweiAv.sizeX() / 2 - 2., lowlimit=.05 * len(particleList), lowval=.05 * len(particleList)) fResult = fft(unweiAv) r = complexRealMult(fResult, wedgeSum) unweiAv = ifft(r) unweiAv.shiftscale( 0.0, 1 / float(unweiAv.sizeX() * unweiAv.sizeY() * unweiAv.sizeZ())) # low pass filter to remove artifacts at fringes unweiAv = lowpassFilter(volume=unweiAv, band=unweiAv.sizeX() / 2 - 2, smooth=(unweiAv.sizeX() / 2 - 1) / 10.)[0] unweiAv.write(averageName) return Reference(averageName, particleList)
def FLCF(volume, template, mask=None, stdV=None): ''' Created on Apr 13, 2010 FLCF: compute the fast local correlation function This functions works only when the mask is in the middle. @param volume: target volume @type volume: L{pytom_volume.vol} @param template: template to be searched. It can have smaller size then target volume. @type template: L{pytom_volume.vol} @param mask: template mask. If not given, a default sphere mask will be generated which has the same size with the given template. @type mask: L{pytom_volume.vol} @param stdV: standard deviation of the target volume under mask, which do not need to be calculated again when the mask is identical. @type stdV: L{pytom_volume.vol} @return: the local correlation function @rtype: L{pytom_volume.vol} @author: Yuxiang Chen ''' from pytom_volume import vol, pasteCenter from pytom.basic.fourier import fft, ifft, iftshift from pytom_volume import conjugate from pytom.basic.structures import Mask from pytom_volume import sum from pytom.basic.files import write_em if volume.__class__ != vol and template.__class__ != vol: raise RuntimeError('Wrong input type!') if volume.sizeX()<template.sizeX() or volume.sizeY()<template.sizeY() or volume.sizeZ()<template.sizeZ(): raise RuntimeError('Template size is bigger than the target volume') # generate the mask if mask.__class__ != vol: from pytom_volume import initSphere mask = vol(template.sizeX(), template.sizeY(), template.sizeZ()) mask.setAll(0) initSphere(mask, template.sizeX()/2,0,0,template.sizeX()/2, template.sizeY()/2, template.sizeZ()/2) else: if template.sizeX()!=mask.sizeX() and template.sizeY()!=mask.sizeY() and template.sizeZ()!=mask.sizeZ(): raise RuntimeError('Template and mask size are not consistent!') # calculate the non-zeros p = sum(mask) # normalize the template under mask meanT = meanValueUnderMask(template, mask, p) stdT = stdValueUnderMask(template, mask, meanT, p) temp = (template - meanT)/stdT temp = temp * mask # construct both the template and the mask which has the same size as target volume tempV = temp if volume.sizeX() != temp.sizeX() or volume.sizeY() != temp.sizeY() or volume.sizeZ() != temp.sizeZ(): tempV = vol(volume.sizeX(), volume.sizeY(), volume.sizeZ()) tempV.setAll(0) pasteCenter(temp, tempV) maskV = mask if volume.sizeX() != mask.sizeX() or volume.sizeY() != mask.sizeY() or volume.sizeZ() != mask.sizeZ(): maskV = vol(volume.sizeX(), volume.sizeY(), volume.sizeZ()) maskV.setAll(0) pasteCenter(mask, maskV) # calculate the mean and std of volume if stdV.__class__ != vol: meanV = meanUnderMask(volume, maskV, p) stdV = stdUnderMask(volume, maskV, p, meanV) size = volume.numelem() fT = fft(tempV) conjugate(fT) result = iftshift(ifft(fT*fft(volume)))/stdV result.shiftscale(0,1/(size*p)) return result
def toProjectionStackFromAlignmentResultsFile(alignmentResultsFile, weighting=None, lowpassFilter=0.9, binning=1, circleFilter=False, num_procs=1, outdir='', prefix='sorted_aligned'): """read image and create aligned projection stack, based on the results described in the alignmentResultFile. @param alignmentResultsFile: result file generate by the alignment script. @type datatypeAR: gui.guiFunction.datatypeAR @param weighting: weighting (<0: analytical weighting, >1: exact weighting, 0/None: no weighting ) @type weighting: float @param lowpassFilter: lowpass filter (in Nyquist) @type lowpassFilter: float @param binning: binning (default: 1 = no binning). binning=2: 2x2 pixels -> 1 pixel, binning=3: 3x3 pixels -> 1 pixel, etc. @author: GvdS """ print('weighting: ', weighting) import numpy from pytom_numpy import vol2npy from pytom.basic.files import read_em, write_em from pytom.basic.functions import taper_edges from pytom.basic.transformations import general_transform2d from pytom.basic.fourier import ifft, fft from pytom.basic.filter import filter as filterFunction, bandpassFilter from pytom.basic.filter import circleFilter, rampFilter, exactFilter, fourierFilterShift, \ fourierFilterShift_ReducedComplex from pytom_volume import complexRealMult, vol, paste import pytom_freqweight from pytom.basic.transformations import resize, rotate from pytom.gui.guiFunctions import fmtAR, headerAlignmentResults, datatype, datatypeAR, loadstar from pytom.reconstruction.reconstructionStructures import Projection, ProjectionList from pytom_numpy import vol2npy import mrcfile from pytom.tompy.io import write, read_size import os print("Create aligned images from alignResults.txt") alignmentResults = loadstar(alignmentResultsFile, dtype=datatypeAR) imageList = alignmentResults['FileName'] tilt_angles = alignmentResults['TiltAngle'] imdim = int(read_size(imageList[0], 'x')) if binning > 1: imdim = int(float(imdim) / float(binning) + .5) else: imdim = imdim sliceWidth = imdim # pre-determine analytical weighting function and lowpass for speedup if (weighting != None) and (float(weighting) < -0.001): weightSlice = fourierFilterShift(rampFilter(imdim, imdim)) if circleFilter: circleFilterRadius = imdim // 2 circleSlice = fourierFilterShift_ReducedComplex( circleFilter(imdim, imdim, circleFilterRadius)) else: circleSlice = vol(imdim, imdim // 2 + 1, 1) circleSlice.setAll(1.0) # design lowpass filter if lowpassFilter: if lowpassFilter > 1.: lowpassFilter = 1. print("Warning: lowpassFilter > 1 - set to 1 (=Nyquist)") # weighting filter: arguments: (angle, cutoff radius, dimx, dimy, lpf = pytom_freqweight.weight(0.0, lowpassFilter * imdim // 2, imdim, imdim // 2 + 1, 1, lowpassFilter / 5. * imdim) # lpf = bandpassFilter(volume=vol(imdim, imdim,1),lowestFrequency=0,highestFrequency=int(lowpassFilter*imdim/2), # bpf=None,smooth=lowpassFilter/5.*imdim,fourierOnly=False)[1] projectionList = ProjectionList() imageList = [] tilt_angles = [] for n, image in enumerate(alignmentResults['FileName']): atx = alignmentResults['AlignmentTransX'][n] aty = alignmentResults['AlignmentTransY'][n] rot = alignmentResults['InPlaneRotation'][n] mag = alignmentResults['Magnification'][n] # print(image, alignmentResults['TiltAngle'][n]) # if abs(alignmentResults['TiltAngle'][n]) > 20: # continue tilt_angles.append(alignmentResults['TiltAngle'][n]) imageList.append(image) projection = Projection(imageList[-1], tiltAngle=tilt_angles[-1], alignmentTransX=atx, alignmentTransY=aty, alignmentRotation=rot, alignmentMagnification=mag) projectionList.append(projection) stack = vol(imdim, imdim, len(imageList)) stack.setAll(0.0) phiStack = vol(1, 1, len(imageList)) phiStack.setAll(0.0) thetaStack = vol(1, 1, len(imageList)) thetaStack.setAll(0.0) offsetStack = vol(1, 2, len(imageList)) offsetStack.setAll(0.0) for (ii, projection) in enumerate(projectionList): if projection._filename.split('.')[-1] == 'st': from pytom.basic.files import EMHeader, read idx = projection._index image = read(file=projection._filename, subregion=[0, 0, idx - 1, imdim, imdim, 1], sampling=[0, 0, 0], binning=[0, 0, 0]) if not (binning == 1) or (binning == None): image = resize(volume=image, factor=1 / float(binning))[0] else: # read projection files from pytom.basic.files import EMHeader, read, read_em_header image = read(str(projection._filename)) # image = rotate(image,180.,0.,0.) image = resize(volume=image, factor=1 / float(binning))[0] if lowpassFilter: filtered = filterFunction(volume=image, filterObject=lpf, fourierOnly=False) image = filtered[0] tiltAngle = projection._tiltAngle # normalize to contrast - subtract mean and norm to mean immean = vol2npy(image).mean() image = (image - immean) / immean print(ii, immean, projection._filename) # smoothen borders to prevent high contrast oscillations image = taper_edges(image, imdim // 30)[0] # transform projection according to tilt alignment transX = projection._alignmentTransX / binning transY = projection._alignmentTransY / binning rot = float(projection._alignmentRotation) mag = float(projection._alignmentMagnification) image = general_transform2d(v=image, rot=rot, shift=[transX, transY], scale=mag, order=[2, 1, 0], crop=True) # smoothen once more to avoid edges image = taper_edges(image, imdim // 30)[0] # analytical weighting if (weighting != None) and (weighting < 0): # image = (ifft(complexRealMult(fft(image), w_func)) / (image.sizeX() * image.sizeY() * image.sizeZ())) image = ifft(complexRealMult( complexRealMult(fft(image), weightSlice), circleSlice), scaling=True) elif (weighting != None) and (weighting > 0): weightSlice = fourierFilterShift( exactFilter(tilt_angles, tiltAngle, imdim, imdim, sliceWidth)) # image = (ifft(complexRealMult(fft(image), w_func)) / (image.sizeX() * image.sizeY() * image.sizeZ())) image = ifft(complexRealMult( complexRealMult(fft(image), weightSlice), circleSlice), scaling=True) thetaStack(int(round(projection.getTiltAngle())), 0, 0, ii) offsetStack(int(round(projection.getOffsetX())), 0, 0, ii) offsetStack(int(round(projection.getOffsetY())), 0, 1, ii) paste(image, stack, 0, 0, ii) fname = '{}_{:02d}.mrc'.format( prefix, int(imageList[ii].split('_')[-1].split('.')[0])) if outdir: import mrcfile # write_em(os.path.join(outdir, fname.replace('mrc', 'em')), image) write(os.path.join(outdir, fname), vol2npy(image).copy().astype('float32')) print('written file: ', fname) return [stack, phiStack, thetaStack, offsetStack]
def apply(self, volume, bypassFlag=False, downscale=1, particle=None): """ apply: Performs preprocessing of volume and reference @param volume: volume to be pre-processed @type volume: L{pytom_volume.vol} @param bypassFlag: Set if only bandpassFilter needed. False otherwise and all routines will be processed. @param downscale: not used anymore @param particle: particle Volume to be subtracted from input volume @type particle: L{pytom_volume.vol} @return: Returns modified volume @author: Thomas Hrabe """ from pytom_volume import vol if self._bandpassOn: from pytom.basic.filter import bandpassFilter # if frequencies specified in Nyquist, 0.5 being highest # fixed wrong adjustment of frequencies upon binning - FF if self._highestFrequency < 1: highestFrequency = self._highestFrequency * volume.sizeX() lowestFrequency = self._lowestFrequency * volume.sizeX() else: highestFrequency = self._highestFrequency lowestFrequency = self._lowestFrequency v = bandpassFilter(volume=volume, lowestFrequency=lowestFrequency, highestFrequency=highestFrequency, bpf=0, smooth=self._bandpassSmooth) volume = v[0] if self._prerotateOn and (not bypassFlag): from pytom_volume import rotate rot = vol(volume.sizeX(), volume.sizeY(), volume.sizeZ()) rotation = self.prerotate rotate(volume, rot, rotation[0], rotation[1], rotation[2]) volume = rot if self._weightingOn and (not bypassFlag): from pytom_volume import read from pytom_freqweight import weight from pytom.basic.fourier import fft, ifft wedgeSum = read(self._weightingFile) fVolume = fft(volume) weighting = weight(wedgeSum) weighting.apply(fVolume) volume = ifft(fVolume) if self._substractParticle and particle.__class__ == vol: volume -= particle if self._taper > 0: from pytom.tools.macros import volumesSameSize if self._taperMask is None or not volumesSameSize( volume, self._taperMask): from pytom.basic.functions import taper_edges volume, self._taperMask = taper_edges(volume, self._taper) else: volume = volume * self._taperMask return volume