def peakCoef(self, volume, reference, mask=None): """ peakCoef: Determines the coefficient of the scoring function. @param volume: A volume. @type volume: L{pytom_volume.vol} @param reference: A reference. @type reference: L{pytom_volume.vol} @return: The highest coefficient determined. @author: Thomas Hrabe, FF """ from pytom_volume import peak from pytom.tools.maths import euclidianDistance from pytom.basic.correlation import subPixelPeak if mask is None: resFunction = self.scoringFunction(volume, reference) else: resFunction = self.scoringFunction(volume, reference, mask) # change FF: 07.01.2020 #centerX = resFunction.sizeX()//2 -1 #centerY = resFunction.sizeY()//2 -1 #centerZ = resFunction.sizeZ()//2 -1 pcoarse = peak(resFunction) p = subPixelPeak(scoreVolume=resFunction, coordinates=pcoarse) #p = subPixelPeak(scoreVolume=resFunction, coordinates=[centerX,centerY,centerZ]) #if euclidianDistance([centerX,centerY,centerZ],p[1]) <= 1.4142135623730951: # c = p[0] return p[0]
def exMaxAlign(self, niter=10, mask=None): """ expectation maximization alignment of imageStack @param niter: number of iterations @type niter: L{int} @param mask: mask applied to average before alignment @type mask: L{pytom_volume.vol} @author: FF """ from pytom.basic.correlation import nXcf, subPixelPeak from pytom_volume import peak for iexMax in range(0, niter): if self.verbose: print("Starting Ex-Max iteration " + str(iexMax + 1) + " of " + str(niter)) meanX = 0. meanY = 0. #Max - step self.average(mask=mask) # Ex-step for ii in range(0, len(self.images)): ccf = nXcf(volume=self.images[ii].data, template=self.subtractImageFromAverage(ii=ii, mask=mask)) pos = peak(ccf) peakinfo = subPixelPeak(scoreVolume=ccf, coordinates=pos, cubeLength=8, verbose=self.verbose) peakval = peakinfo[0] pos = peakinfo[1] self.images[ii].shiftX = float(pos[0] - self.dimX) self.images[ii].shiftY = float(pos[1] - self.dimY) meanX = meanX + self.images[ii].shiftX meanY = meanY + self.images[ii].shiftY # set mean shifts to 0 meanX = meanX / len(self.images) meanY = meanY / len(self.images) for ii in range(0, len(self.images)): self.images[ii].shiftX = self.images[ii].shiftX - meanX self.images[ii].shiftY = self.images[ii].shiftY - meanY
def bestAlignmentGPU(particleList, rotations, plan, isSphere=True): """ bestAlignment: Determines best alignment of particle relative to the reference @param particle: A particle @type particle: L{pytom_volume.vol} @param reference: A reference @type reference: L{pytom_volume.vol} @param referenceWeighting: Fourier weighting of the reference (sum of wedges for instance) @type referenceWeighting: L{pytom.basic.structures.vol} @param wedgeInfo: What does the wedge look alike? @type wedgeInfo: L{pytom.basic.structures.Wedge} @param rotations: All rotations to be scanned @type rotations: L{pytom.angles.AngleObject} @param scoreObject: @type scoreObject: L{pytom.score.score.Score} @param mask: real-space mask for correlation function @type mask: L{pytom.basic.structures.Particle} @param preprocessing: Class storing preprocessing of particle and reference such as bandpass @type preprocessing: L{pytom.alignment.preprocessing.Preprocessing} @param progressBar: Display progress bar of alignment. False by default. @param binning: binning factor - e.g. binning=2 reduces size by FACTOR of 2 @type binning: int or float @param bestPeak: Initialise best peak with old values. @param verbose: Print out infos. Writes CC volume to disk!!! Default is False @return: Returns the best rotation for particle and the corresponding scoring result. @author: Thomas Hrabe """ from pytom.gpu.tools import add_particle_to_sum from pytom.gpu.prepare_plans import prepare_glocal_plan from pytom.gpu.correlation import subPixelPeak, find_coords_max_ccmap from pytom.gpu.filter import filter, applyWedge from pytom.gpu.preprocessing import applyPreprocessing from pytom.gpu.transformations import resize, resizeFourier, rotate import numpy as np binningType = 'Fourier' # or 'Fourier' bestPeakList = [] for pid, particle in particleList: centerCoordinates = np.array([size//2 for size in plan.shape], dtype=np.int32) # create buffer volume for transformed particle applyWedge(particle) # apply wedge to itself applyPreprocessing(particle, taper=np.float32(shape[0] / 10.) ) # filter particle to some resolution bestPeak = [-1000, [0,0,0], [0,0,0]] for n, currentRotation in enumerate(rotations): if not isSphere: meanUnderMask(particle, plan.mask, plan.p) stdUnderMask(particle, plan.mask, plan.p, plan.meanV) rotateWedge(plan.reference, currentRotation, plan.wedge, plan.mask, centerCoordinates) applyPreprocessing(plan.simulatedVol, bypassFlag=True) # weight particle rotateWeight(plan.reference, plan.referenceWeighting, currentRotation) filterParticle(particle, weight(weightingRotated), plan.particleCopy) cross_correlation(plan.particleCopy, plan.simulatedVol, plan.ccc_map) peakCoordinates = find_coords_max_ccmap(plan.ccc_map) # with subPixelPeak [peakValue, peakPosition] = subPixelPeak(plan.ccc_map, coordinates=peakCoordinates, cropsize=10) # determine shift relative to center shiftX = (peakPosition[0] - centerX) shiftY = (peakPosition[1] - centerY) shiftZ = (peakPosition[2] - centerZ) newPeak = (peakValue, currentRotation, (shiftX, shiftY, shiftZ)) if bestPeak[0] < newPeak[0]: bestPeak = newPeak if pid % 2 == 0: add_particle_to_sum(particle, bestPeak[1][::-1]*-1, plan.evenSum) else: add_particle_to_sum(particle, bestPeak[1][::-1]*-1, plan.oddSum) bestPeakList.append(bestPeak) return bestPeakList
def bestAlignment(particle, reference, referenceWeighting, wedgeInfo, rotations, scoreObject=0, mask=None, preprocessing=None, progressBar=False, binning=1, bestPeak=None, verbose=False): """ bestAlignment: Determines best alignment of particle relative to the reference @param particle: A particle @type particle: L{pytom_volume.vol} @param reference: A reference @type reference: L{pytom_volume.vol} @param referenceWeighting: Fourier weighting of the reference (sum of wedges for instance) @type referenceWeighting: L{pytom.basic.structures.vol} @param wedgeInfo: What does the wedge look alike? @type wedgeInfo: L{pytom.basic.structures.Wedge} @param rotations: All rotations to be scanned @type rotations: L{pytom.angles.AngleObject} @param scoreObject: @type scoreObject: L{pytom.score.score.Score} @param mask: real-space mask for correlation function @type mask: L{pytom.basic.structures.Particle} @param preprocessing: Class storing preprocessing of particle and reference such as bandpass @type preprocessing: L{pytom.alignment.preprocessing.Preprocessing} @param progressBar: Display progress bar of alignment. False by default. @param binning: binning factor - e.g. binning=2 reduces size by FACTOR of 2 @type binning: int or float @param bestPeak: Initialise best peak with old values. @param verbose: Print out infos. Writes CC volume to disk!!! Default is False @return: Returns the best rotation for particle and the corresponding scoring result. @author: Thomas Hrabe """ from pytom.basic.correlation import subPixelPeak, subPixelPeakParabolic from pytom.alignment.structures import Peak from pytom_volume import peak, vol, vol_comp from pytom.basic.filter import filter,rotateWeighting from pytom.basic.structures import Rotation, Shift, Particle, Mask from pytom.angles.angle import AngleObject from pytom.alignment.preprocessing import Preprocessing from pytom.basic.transformations import resize, resizeFourier binningType = 'Fourier' # or 'Fourier' assert isinstance(rotations, AngleObject), "bestAlignment: rotations must be " \ "AngleObject!" currentRotation = rotations.nextRotation() if currentRotation == [None,None,None]: raise Exception('bestAlignment: No rotations are sampled! Something is wrong with input rotations') assert particle.__class__ == vol, "particle not of type vol" assert reference.__class__ == vol, "reference not of type vol" assert (referenceWeighting.__class__ == vol or referenceWeighting.__class__ == str), \ "referenceWeighting not volume or str" if mask: assert mask.__class__ == Mask, "Mask not of type Mask" m = mask.getVolume() if scoreObject == 0 or not scoreObject: from pytom.score.score import xcfScore scoreObject = xcfScore() # fix binning if binning == 0: binning = 1 if binning != 1: particleUnbinned = vol(particle.sizeX(), particle.sizeY(), particle.sizeZ()) particleUnbinned.copyVolume(particle) particle = resize(volume=particle, factor=1./binning, interpolation=binningType) if type(particle) == tuple: particle = particle[0] referenceUnbinned = vol(reference.sizeX(), reference.sizeY(), reference.sizeZ()) referenceUnbinned.copyVolume(reference) reference = resize(volume=reference, factor=1./binning, interpolation=binningType) if type(reference) == tuple: reference = reference[0] if mask: m = resize(volume=m, factor=1./binning, interpolation='Spline') if not referenceWeighting.__class__ == str: referenceWeightingUnbinned = vol_comp(referenceWeighting.sizeX(), referenceWeighting.sizeY(), referenceWeighting.sizeZ()) referenceWeightingUnbinned.copyVolume(referenceWeighting) if binning != 1: referenceWeighting = resizeFourier(fvol=referenceWeighting, factor=1./binning) centerX, centerY, centerZ = int(particle.sizeX()/2), int(particle.sizeY()/2), int(particle.sizeZ()/2) # create buffer volume for transformed particle particleCopy = vol(particle.sizeX(),particle.sizeY(),particle.sizeZ()) particle = wedgeInfo.apply(particle) #apply wedge to itself if preprocessing is None: preprocessing = Preprocessing() preprocessing.setTaper( taper=particle.sizeX()/10.) particle = preprocessing.apply(volume=particle, bypassFlag=True) # filter particle to some resolution particleCopy.copyVolume(particle) # compute standard veviation volume really only if needed if mask and (scoreObject._type=='FLCFScore'): from pytom_volume import sum from pytom.basic.correlation import meanUnderMask, stdUnderMask p = sum(m) meanV = meanUnderMask(particle, m, p) stdV = stdUnderMask(particle, m, p, meanV) else: meanV = None stdV = None while currentRotation != [None,None,None]: if mask: m = mask.getVolume(currentRotation) if binning != 1: m = resize(volume=m, factor=1./binning, interpolation='Spline') #update stdV if mask is not a sphere # compute standard deviation volume really only if needed if not mask.isSphere() and (scoreObject._type=='FLCFScore'): meanV = meanUnderMask(particle, m, p) stdV = stdUnderMask(particle, m, p, meanV) else: m = None simulatedVol = _rotateWedgeReference(reference, currentRotation, wedgeInfo, m, [centerX, centerY, centerZ]) simulatedVol = preprocessing.apply(volume=simulatedVol, bypassFlag=True) #weight particle if not referenceWeighting.__class__ == str: from pytom_freqweight import weight weightingRotated = rotateWeighting(weighting=referenceWeighting, z1=currentRotation[0], z2=currentRotation[1], x=currentRotation[2], isReducedComplex=True, returnReducedComplex=True, binarize=False) particleCopy.copyVolume(particle) r = list(filter(particleCopy, weight(weightingRotated))) particleCopy = r[0] scoringResult = scoreObject.score(particleCopy, simulatedVol, m, stdV) pk = peak(scoringResult) #with subPixelPeak [peakValue,peakPosition] = subPixelPeak(scoreVolume=scoringResult, coordinates=pk, interpolation='Quadratic', verbose=False) #[peakValue,peakPosition] = subPixelPeakParabolic(scoreVolume=scoringResult, coordinates=pk, verbose=False) # determine shift relative to center shiftX = (peakPosition[0] - centerX) * binning shiftY = (peakPosition[1] - centerY) * binning shiftZ = (peakPosition[2] - centerZ) * binning #NANs would fail this test. assert peakValue == peakValue, "peakValue seems to be NaN" newPeak = Peak(peakValue, Rotation(currentRotation), Shift(shiftX, shiftY, shiftZ)) if verbose: print('Rotation: z1=%3.1f, z2=%3.1f, x=%3.1f; Dx=%2.2f, Dy=%2.2f, Dz=%2.2f, CC=%2.3f' % \ (currentRotation[0], currentRotation[1], currentRotation[2], shiftX, shiftY, shiftZ, peakValue)) if bestPeak is None: bestPeak = newPeak if verbose: scoringResult.write('BestScore.em') if bestPeak < newPeak: bestPeak = newPeak if verbose: scoringResult.write('BestScore.em') currentRotation = rotations.nextRotation() # repeat ccf for binned sampling to get translation accurately if binning != 1: m = mask.getVolume(bestPeak.getRotation()) centerX, centerY, centerZ = int(particleUnbinned.sizeX()/2), int(particleUnbinned.sizeY()/2), \ int(particleUnbinned.sizeZ()/2) simulatedVol = _rotateWedgeReference(referenceUnbinned, bestPeak.getRotation(), wedgeInfo, m, [centerX, centerY, centerZ]) simulatedVol = preprocessing.apply(volume=simulatedVol, bypassFlag=True) if mask and scoreObject._type=='FLCFScore': p = sum(m) meanV = meanUnderMask(volume=particleUnbinned, mask=m, p=p) stdV = stdUnderMask(volume=particleUnbinned, mask=m, p=p, meanV=meanV) scoreObject._peakPrior.reset_weight() scoringResult = scoreObject.score(particle=particleUnbinned, reference=simulatedVol, mask=m, stdV=stdV) pk = peak(scoringResult) [peakValue,peakPosition] = subPixelPeak(scoreVolume=scoringResult, coordinates=pk, interpolation='Quadratic', verbose=False) shiftX = (peakPosition[0] - centerX) shiftY = (peakPosition[1] - centerY) shiftZ = (peakPosition[2] - centerZ) bestPeak = Peak(peakValue, bestPeak.getRotation(), Shift(shiftX, shiftY, shiftZ)) if verbose: print('BestAlignment: z1=%3.1f, z2=%3.1f, x=%3.1f; Dx=%2.2f, Dy=%2.2f, Dz=%2.2f, CC=%2.3f' % \ (bestPeak.getRotation()[0], bestPeak.getRotation()[1], bestPeak.getRotation()[2], bestPeak.getShift()[0], bestPeak.getShift()[1], bestPeak.getShift()[2], bestPeak.getScoreValue())) rotations.reset() scoreObject._peakPrior.reset_weight() return bestPeak