def dev(volume, template, mask=None, volumeIsNormalized=False): """ dev: Calculates the squared deviation of volume and template in real space @param volume: A volume @type volume: L{pytom_volume.vol} @param template: A template that is searched in volume. Must be of same size as volume. @type template: L{pytom_volume.vol} @param mask: mask to constrain correlation @type mask: L{pytom_volume.vol} @param volumeIsNormalized: speed up if volume is already normalized @type volumeIsNormalized: L{bool} @return: deviation @raise exception: Raises a runtime error if volume and template have a different size. @author: FF """ from pytom_volume import vol,sum from pytom.tools.macros import volumesSameSize assert type(volume) == vol, "dev: volume has to be of type vol!" assert type(template) == vol, "dev: template has to be of type vol!" if not volumesSameSize(volume,template): raise RuntimeError('Volume and template must have same size!') if not mask: p = volume.numelem() result = volume-template else: assert type(mask) == vol, "dev: mask has to be of type vol!" p = sum(mask) result = (volume-template)*mask deviat = sum(result**2) deviat = deviat / float(p) return deviat
def meanValueUnderMask(volume, mask=None, p=None): """ meanValueUnderMask: Determines the mean value under a mask @param volume: The volume @type volume: L{pytom_volume.vol} @param mask: The mask @type mask: L{pytom_volume.vol} @param p: precomputed number of voxels in mask @type p: float @return: A value (scalar) @rtype: single @change: support None as mask, FF 08.07.2014 """ from pytom_volume import vol, sum if not volume.__class__ == vol: raise TypeError("meanValueUnderMask: Volume parameter must be of type vol!") if mask: if not p: p = sum(mask) resV = volume*mask res = sum(resV)/p else: res = sum(volume)/(volume.sizeX()*volume.sizeY()*volume.sizeZ()) return res
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 theta_vol_projection(vol_src, theta): from pytom_volume import vol from pytom_volume import rotate from pytom_volume import subvolume from pytom_volume import sum vol_src_dim_x = vol_src.sizeX() vol_src_dim_y = vol_src.sizeY() vol_src_dim_z = vol_src.sizeZ() vol_dst = vol(vol_src_dim_x, vol_src_dim_y, vol_src_dim_z) vol_dst.setAll(0.0) rotate(vol_src, vol_dst, 270, 90, theta) vol_img = vol(vol_src_dim_x, vol_src_dim_y, 1) vol_img.setAll(0.0) for i in range(vol_src_dim_x): for j in range(vol_src_dim_y): vol_img.setV(sum(subvolume(vol_dst, i, j, 0, 1, 1, vol_src_dim_z)), i, j, 0) return vol_img
def normaliseUnderMask(volume, mask, p=None): """ normalize volume within a mask - take care: only normalization, but NOT multiplication with mask! @param volume: volume for normalization @type volume: pytom volume @param mask: mask @type mask: pytom volume @param p: sum of gray values in mask (if pre-computed) @type p: C{int} or C{float} @return: volume normalized to mean=0 and std=1 within mask, p @rtype: C{list} @author: FF """ from pytom.basic.correlation import meanValueUnderMask, stdValueUnderMask #from math import sqrt if not p: from pytom_volume import sum p = sum(mask) #meanT = sum(volume) / p ## subtract mean and mask #res = mask * (volume - meanT) #stdT = sum(res*res) / p #stdT = sqrt(stdT) #res = res / stdT meanT = meanValueUnderMask(volume, mask, p) stdT = stdValueUnderMask(volume, mask, meanT, p) res = (volume - meanT)/stdT return (res,p)
def xcc(volume,template,mask=None, volumeIsNormalized=False): """ xcc: Calculates the cross correlation coefficient in real space @param volume: A volume @type volume: L{pytom_volume.vol} @param template: A template that is searched in volume. Must be of same size as volume. @type template: L{pytom_volume.vol} @param mask: mask to constrain correlation @type mask: L{pytom_volume.vol} @param volumeIsNormalized: only used for compatibility with nxcc - not used @type volumeIsNormalized: L{bool} @return: A unscaled value @raise exception: Raises a runtime error if volume and template have a different size. @author: Thomas Hrabe """ from pytom_volume import sum from pytom.tools.macros import volumesSameSize if not volumesSameSize(volume,template): raise RuntimeError('Volume and template must have same size!') if mask: # mask is given result = mask * volume * template else: result = volume * template cc = sum(result) cc = cc / float(volume.numelem()) return cc
def transform_single_vol(vol1, mask): from pytom_volume import sum from pytom.basic.correlation import meanValueUnderMask, stdValueUnderMask, meanUnderMask, stdUnderMask p = sum(mask) meanV = meanUnderMask(vol1, mask, p) stdV = stdUnderMask(vol1, mask, p, meanV) result = (vol1 - meanV) / stdV return result
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 nxcc(volume, template, mask=None, volumeIsNormalized=False): """ nxcc: Calculates the normalized cross correlation coefficient in real space @param volume: A volume @type volume: L{pytom_volume.vol} @param template: A template that is searched in volume. Must be of same size as volume. @type template: L{pytom_volume.vol} @param mask: mask to constrain correlation @type mask: L{pytom_volume.vol} @param volumeIsNormalized: speed up if volume is already normalized @type volumeIsNormalized: L{bool} @return: A value between -1 and 1 @raise exception: Raises a runtime error if volume and template have a different size. @author: Thomas Hrabe @change: flag for pre-normalized volume, FF """ from pytom_volume import vol,sum,limit from pytom.tools.macros import volumesSameSize if not volumesSameSize(volume,template): raise RuntimeError('Volume and template must have same size!') if not mask: from pytom.basic.normalise import mean0std1 if not volumeIsNormalized: v = mean0std1(volume, True) t = mean0std1(template, True) p = volume.numelem() result = v*t else: from pytom_numpy import vol2npy from pytom.basic.normalise import normaliseUnderMask if not volumeIsNormalized: (v,p) = normaliseUnderMask(volume, mask) (t,p) = normaliseUnderMask(template, mask, p) t = t * mask # multiply with the mask result = v * t else: (t,p) = normaliseUnderMask(template,mask) t = t * mask # multiply with the mask result = volume * t ncc = sum(result) ncc = ncc / float(p) return ncc
def stdValueUnderMask(volume, mask, meanValue, p=None): """ stdValueUnderMask: Determines the std value under a mask @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{float} or L{int} @return: A value @rtype: L{float} @change: support None as mask, FF 08.07.2014 """ from pytom_volume import sum from pytom_volume import vol, power, variance assert volume.__class__ == vol if mask: if not p: p = sum(mask) else: p = volume.sizeX()*volume.sizeY()*volume.sizeZ() squareM = meanValue**2 squareV = vol(volume.sizeX(), volume.sizeY(), volume.sizeZ()) squareV.copyVolume(volume) power(squareV, 2) res = meanValueUnderMask(squareV, mask, p) res = res - squareM try: res = res**0.5 except ValueError: print("Res = %.6f < 0 => standard deviation determination fails :(") print(" something went terribly wrong and program has to stop") raise ValueError('Program stopped in stdValueUnderMask') return res
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
def extractPeaks(volume, reference, rotations, scoreFnc=None, mask=None, maskIsSphere=False, wedgeInfo=None, **kwargs): ''' Created on May 17, 2010 @param volume: target volume @type volume: L{pytom_volume.vol} @param reference: reference @type reference: L{pytom_volume.vol} @param rotations: rotation angle list @type rotations: L{pytom.angles.globalSampling.GlobalSampling} @param scoreFnc: score function that is used @type scoreFnc: L{pytom.basic.correlation} @param mask: mask volume @type mask: L{pytom_volume.vol} @param maskIsSphere: flag to indicate whether the mask is sphere or not @type maskIsSphere: boolean @param wedgeInfo: wedge information @type wedgeInfo: L{pytom.basic.structures.WedgeInfo} @return: both the score volume and the corresponding rotation index volume @rtype: L{pytom_volume.vol} @author: chen ''' # from pytom.tools.timing import timing # t = timing(); t.start() # parse the parameters nodeName = kwargs.get('nodeName', '') verbose = kwargs.get('verboseMode', True) if verbose not in [True, False]: verbose = True moreInfo = kwargs.get('moreInfo', False) if moreInfo not in [True, False]: moreInfo = False from pytom.basic.correlation import FLCF from pytom.basic.structures import WedgeInfo, Wedge from pytom_volume import vol, pasteCenter from pytom_volume import rotateSpline as rotate # for more accuracy from pytom_volume import updateResFromIdx from pytom.basic.files import write_em if scoreFnc == None: scoreFnc = FLCF # only FLCF needs mask if scoreFnc == FLCF: if mask.__class__ != vol: # construct a sphere mask by default from pytom_volume import initSphere mask = vol(reference.sizeX(), reference.sizeY(), reference.sizeZ()) mask.setAll(0) initSphere(mask, reference.sizeX() / 2, 0, 0, reference.sizeX() / 2, reference.sizeX() / 2, reference.sizeX() / 2) maskIsSphere = True # result volume which stores the score result = vol(volume.sizeX(), volume.sizeY(), volume.sizeZ()) result.setAll(-1) # result orientation of the peak value (index) orientation = vol(volume.sizeX(), volume.sizeY(), volume.sizeZ()) orientation.setAll(0) currentRotation = rotations.nextRotation() index = 0 if verbose == True: from pytom.tools.ProgressBar import FixedProgBar max = rotations.numberRotations() - 1 prog = FixedProgBar(0, max, nodeName) if moreInfo: sumV = vol(volume.sizeX(), volume.sizeY(), volume.sizeZ()) sumV.setAll(0) sqrV = vol(volume.sizeX(), volume.sizeY(), volume.sizeZ()) sqrV.setAll(0) else: sumV = None sqrV = None if wedgeInfo.__class__ == WedgeInfo or wedgeInfo.__class__ == Wedge: print('Applied wedge to volume') volume = wedgeInfo.apply(volume) while currentRotation != [None, None, None]: if verbose == True: prog.update(index) # rotate the reference ref = vol(reference.sizeX(), reference.sizeY(), reference.sizeZ()) rotate(reference, ref, currentRotation[0], currentRotation[1], currentRotation[2]) # apply wedge if wedgeInfo.__class__ == WedgeInfo or wedgeInfo.__class__ == Wedge: ref = wedgeInfo.apply(ref) # rotate the mask if it is asymmetric if scoreFnc == FLCF: if maskIsSphere == False: # if mask is not a sphere, then rotate it m = vol(mask.sizeX(), mask.sizeY(), mask.sizeZ()) rotate(mask, m, currentRotation[0], currentRotation[1], currentRotation[2]) else: m = mask # compute the score # if mask is sphere and it is the first run, compute the standard deviation of the volume under mask for late use if scoreFnc == FLCF and index == 0 and maskIsSphere == True: # compute standard deviation of the volume under mask maskV = m if volume.sizeX() != m.sizeX() or volume.sizeY() != m.sizeY( ) or volume.sizeZ() != m.sizeZ(): maskV = vol(volume.sizeX(), volume.sizeY(), volume.sizeZ()) maskV.setAll(0) pasteCenter(m, maskV) from pytom_volume import sum p = sum(m) from pytom.basic.correlation import meanUnderMask, stdUnderMask meanV = meanUnderMask(volume, maskV, p) stdV = stdUnderMask(volume, maskV, p, meanV) # ref.write('template_cpu.em') if scoreFnc == FLCF: if maskIsSphere == True: score = scoreFnc(volume, ref, m, stdV, wedge=1) else: score = scoreFnc(volume, ref, m) else: # not FLCF, so doesn't need mask as parameter and perhaps the reference should have the same size _ref = vol(volume.sizeX(), volume.sizeY(), volume.sizeZ()) _ref.setAll(0) pasteCenter(ref, _ref) score = scoreFnc(volume, _ref) # update the result volume and the orientation volume updateResFromIdx(result, score, orientation, index) if moreInfo: sumV = sumV + score sqrV = sqrV + score * score currentRotation = rotations.nextRotation() index = index + 1 # if moreInfo: # sumV = sumV/rotations.numberRotations() # sqrV = sqrV/rotations.numberRotations() # time = t.end(); print 'The overall execution time: %f' % time return [result, orientation, sumV, sqrV]
def bandCC(volume,reference,band,verbose = False): """ 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 """ import pytom_volume from pytom.basic.filter import bandpassFilter from pytom.basic.correlation import xcf from math import sqrt if verbose: print('lowest freq : ', band[0],' highest freq' , band[1]) vf = bandpassFilter(volume,band[0],band[1],fourierOnly=True) rf = bandpassFilter(reference,band[0],band[1],vf[1],fourierOnly=True) ccVolume = pytom_volume.vol_comp(rf[0].sizeX(),rf[0].sizeY(),rf[0].sizeZ()) ccVolume.copyVolume(rf[0]) pytom_volume.conj_mult(ccVolume,vf[0]) cc = pytom_volume.sum(ccVolume) cc = cc.real v = vf[0] r = rf[0] absV = pytom_volume.abs(v) absR = pytom_volume.abs(r) pytom_volume.power(absV,2) pytom_volume.power(absR,2) sumV = pytom_volume.sum(absV) sumR = pytom_volume.sum(absR) sumV = abs(sumV) sumR = abs(sumR) if sumV == 0: sumV =1 if sumR == 0: sumR =1 cc = cc / (sqrt(sumV*sumR)) #numerical errors will be punished with nan if abs(cc) > 1.1 : cc = float('nan') return [cc,vf[1]];
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