def determine_resolution(self, even, odd, criterion, numberBands, mask, verbose=False): """For the master node, determine the resolution. """ from pytom.basic.correlation import FSC, determineResolution if not numberBands: numberBands = even.sizeX() / 2 fsc = FSC(even, odd, numberBands, mask, verbose=False) if verbose: print(self.node_name + ': FSC: ' + str(fsc)) return determineResolution(fsc, criterion, verbose=False)
def determine_resolution(self, even, odd, criterion, numberBands, mask, verbose=False): """For the master node, determine the resolution. @param even: particle list even @type even: L{pytom.basic.structures.ParticleList} @param odd: particle list odd @type odd: L{pytom.basic.structures.ParticleList} """ from pytom.basic.correlation import FSC, determineResolution if not numberBands: numberBands = even.sizeX() / 2 fsc = FSC(even, odd, numberBands, mask, verbose=False) if verbose: print(self.node_name + ': FSC: ' + str(fsc)) return determineResolution(fsc, criterion, verbose=False)
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 alignVolumesAndFilterByFSC(vol1, vol2, mask=None, nband=None, iniRot=None, iniTrans=None, interpolation='linear', fsc_criterion=0.143, verbose=0): """ align two volumes, compute their FSC, and filter by FSC @param vol1: volume 1 @param vol2: volume 2 @mask: mask volume @type mask: L{pytom_volume.vol} @param nband: Number of bands @type nband: L{int} @param iniRot: initial guess for rotation @param iniTrans: initial guess for translation @param interpolation: interpolation type - 'linear' (default) or 'spline' @param fsc_criterion: filter -> 0 according to resolution criterion @type fsc_criterion: float @param verbose: verbose level (0=mute, 1 some output, 2=talkative) @type verbose: int @type interpolation: str @return: (filvol1, filvol2, fsc, fsc_fil, optiRot, optiTrans) i.e., filtered volumes, their FSC, the corresponding\ filter that was applied to the volumes, and the optimal rotation and translation of vol2 with respect to vol1\ note: filvol2 is NOT rotated and translated! @author: FF """ from pytom_volume import transformSpline, vol from pytom.basic.correlation import FSC from pytom.basic.filter import filter_volume_by_profile from pytom.alignment.localOptimization import Alignment from pytom.basic.correlation import nxcc assert isinstance(object=vol1, class_or_type_or_tuple=vol ), "alignVolumesAndFilterByFSC: vol1 must be of type vol" assert isinstance(object=vol2, class_or_type_or_tuple=vol ), "alignVolumesAndFilterByFSC: vol2 must be of type vol" # filter volumes prior to alignment according to SNR fsc = FSC(volume1=vol1, volume2=vol2, numberBands=nband) fil = design_fsc_filter(fsc=fsc, fildim=int(vol2.sizeX() / 2)) #filter only one volume so that resulting CCC is weighted by SNR only once filvol2 = filter_volume_by_profile(volume=vol2, profile=fil) # align vol2 to vol1 if verbose == 2: alignment = Alignment(vol1=vol1, vol2=filvol2, score=nxcc, mask=mask, iniRot=iniRot, iniTrans=iniTrans, opti='fmin_powell', interpolation=interpolation, verbose=verbose) else: alignment = Alignment(vol1=vol1, vol2=filvol2, score=nxcc, mask=mask, iniRot=iniRot, iniTrans=iniTrans, opti='fmin_powell', interpolation=interpolation, verbose=False) optiScore, optiRot, optiTrans = alignment.localOpti(iniRot=iniRot, iniTrans=iniTrans) if verbose: from pytom.angles.angleFnc import differenceAngleOfTwoRotations from pytom.basic.structures import Rotation diffAng = differenceAngleOfTwoRotations(rotation1=Rotation(0, 0, 0), rotation2=optiRot) print( "Alignment densities: Rotations: %2.3f, %2.3f, %2.3f; Translations: %2.3f, %2.3f, %2.3f " % (optiRot[0], optiRot[1], optiRot[2], optiTrans[0], optiTrans[1], optiTrans[2])) print("Orientation difference: %2.3f deg" % diffAng) vol2_alig = vol(vol2.sizeX(), vol2.sizeY(), vol2.sizeZ()) transformSpline(vol2, vol2_alig, optiRot[0], optiRot[1], optiRot[2], int(vol2.sizeX() / 2), int(vol2.sizeY() / 2), int(vol2.sizeY() / 2), 0, 0, 0, optiTrans[0], optiTrans[1], optiTrans[2]) # finally compute FSC and filter of both volumes if not nband: nband = int(vol2.sizeX() / 2) fsc = FSC(volume1=vol1, volume2=vol2_alig, numberBands=nband) fil = design_fsc_filter(fsc=fsc, fildim=int(vol2.sizeX() / 2), fsc_criterion=fsc_criterion) filvol1 = filter_volume_by_profile(volume=vol1, profile=fil) #filvol2 = filter_volume_by_profile( volume=vol2_alig, profile=fil) filvol2 = filter_volume_by_profile(volume=vol2, profile=fil) return (filvol1, filvol2, fsc, fil, optiRot, optiTrans)
for i in xrange(n): print i vl2 = vol(vl) rotate(vl2, vl, step, 0, 0) vc2 = vol(vc) rotateCubic(vc2, vc, step, 0, 0) vs2 = vol(vs) rotateSpline(vs2, vs, step, 0, 0) vf = rotateFourierSpline(vf, step, 0, 0) vv = fourier_rotate_vol(vv, [step, 0, 0]) # step = -step vl.write('vl.em') vc.write('vc.em') vs.write('vs.em') vf.write('vf.em') vv.write('vv.em') sl = FSC(v, vl, v.sizeX() / 2) sc = FSC(v, vc, v.sizeX() / 2) ss = FSC(v, vs, v.sizeX() / 2) sf = FSC(v, vf, v.sizeX() / 2) sv = FSC(v, vv, v.sizeX() / 2) print sl print sc print ss print sf print sv
randomize = float(randomize) except ValueError or randomize > 1 or randomize < 0: raise ValueError( 'The value of randomizePhases should be a float between 0 and 1.') if outdir is None: outdir = './' if v1Filename and v2Filename: v1 = read(v1Filename) v2 = read(v2Filename) if not numberBands: numberBands = int(v1.sizeX() // 2) f = FSC(v1, v2, numberBands, mask, verbose) #f = [1, 0.9999816330959427, 0.9998727543638058, 0.9986706311763134, 0.9967503089610698, 0.9945473896086455, 0.9953391452631559, 0.9926167503040506, 0.9886499997836082, 0.9846988786130074, 0.9850170987613799, 0.9849222409268831, 0.9820779872082366, 0.981161445747785, 0.978102618561267, 0.9749670311874213, 0.9710488103484851, 0.9686564997495193, 0.9643854526532541, 0.9621314730670771, 0.9568606791204185, 0.9488084842261655, 0.9416015322427522, 0.9316703960630233, 0.9106972097966776, 0.8912878863048055, 0.8795187076235272, 0.8713474813842144, 0.8508750246010772, 0.8195820950483931, 0.8065990902773463, 0.7823660922709397, 0.7521861621134768, 0.7236765089946452, 0.6967229052025852, 0.6815563485825349, 0.6606856188994277, 0.6513326589007892, 0.6340321380485363, 0.6057709663336085, 0.584793117868313, 0.5612341962238455, 0.5623548376402193, 0.5564192235463952, 0.5397585867441497, 0.5089376925831242, 0.4647300273454635, 0.4310334881504598, 0.41741429413879966, 0.4195952490948154, 0.4066609275881065, 0.37019375197265786, 0.31936001816491055, 0.275903152373691, 0.2538399661514517, 0.24197349348826183, 0.20730706794873432, 0.1823204187105925, 0.17041895753522998, 0.16153106667416953, 0.13872290716093824, 0.12428131231796732, 0.09594749780671366, 0.09281895056407187, 0.0950512406930502, 0.07845013400157819, 0.06778918720241832, 0.05699422426625805, 0.04004787096713291, 0.035285330785697615, 0.02761223114687527, 0.029854265039150632, 0.030802679570736933, 0.02855574408867763, 0.04062783248396335, 0.046982827702621556, 0.044667285930674615, 0.03327190294513204, 0.028879433147898908, 0.019113096081122542, 0.018889519864393182, 0.03363102079214279, 0.030416314115916717, 0.015045702588444513, 0.007700419599421394, 0.013662921155622407, 0.02549288977161008, 0.01648898979277964, 0.004577992397744576, 0.003687537468279412, 0.015624522796941348, 0.012150048589636583, 0.013236997547964386, 0.024818980351894827, 0.017881736272355488, 0.008875703095090339, 0.004009836930167128, 0.005169522148403328, 0.013778610598594218, 0.024255111798589142] if verbose: print('FSC:\n', f) import pytom.tompy.correlation as correlation from pytom_numpy import vol2npy import numpy as np from pytom.tompy.io import write if randomize is None: for (ii, fscel) in enumerate(f): f[ii] = 2. * fscel / (1. + fscel) r = determineResolution(f, fscCriterion, verbose) else: randomizationFrequency = np.floor( determineResolution(np.array(f), randomize, verbose)[1])