예제 #1
0
def frm_fourier_constrained_vol(vf, mf, vg, mg):
    radius = vf.sizeX() / 2 - 3  # intepolation in the outer part is nonsense
    b = 32

    from pytom.basic.fourier import fft, ifft, ftshift, iftshift

    vf = ftshift(reducedToFull(fft(iftshift(vf, inplace=False))),
                 inplace=False)
    vg = ftshift(reducedToFull(fft(iftshift(vg, inplace=False))),
                 inplace=False)

    vfr = real(vf)
    vfi = imag(vf)
    vgr = real(vg)
    vgi = imag(vg)

    res = np.zeros((2 * b, 2 * b, 2 * b))
    for r in xrange(1, radius + 1):
        corr = frm_fourier_constrained_corr(vol2sf(vfr, r,
                                                   b), vol2sf(vfi, r, b), mf,
                                            vol2sf(vgr, r, b),
                                            vol2sf(vgi, r, b), mg, True)
        res += corr * (r**2)

    return res
예제 #2
0
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
예제 #3
0
파일: fourier.py 프로젝트: mvanevic/PyTom
def convolute(v, k, kernel_in_fourier=False):
    """
    @param v: the volume to be convolute
    @type v: L{pytom_volume.vol}
    @param k: the convolution kernel in real space
    @type k: L{pytom_volume.vol}
    @param kernel_in_fourier: the given kernel is already in Fourier space or not (full size, shifted in the center! \
        or reduced size). Default is False.
    @type kernel_in_fourier: L{bool}
    @return: Volume convoluted with kernel
    @rtype: L{pytom_volume.vol}
    """
    fv = fft(v)
    if not kernel_in_fourier:
        fk = fft(k)
        res = fv*fk
    else:
        from pytom_volume import complexRealMult, fullToReduced
        if k.sizeZ() == k.sizeX():
            fk = fullToReduced(ftshift(k, inplace=False))
        else:
            fk = k
        res = complexRealMult(fv, fk)
        
    out = ifft(res)
    out.shiftscale(0.0,1/float(out.sizeX()*out.sizeY()*out.sizeZ()))
    
    return out
예제 #4
0
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
예제 #5
0
def bandpassFilter(volume, lowestFrequency, highestFrequency, bpf=None, smooth=0,fourierOnly=False):
    """
    bandpassFilter: Performs bandpass filtering of volume.
    @param volume: The volume to be filtered
    @type volume: L{pytom_volume.vol}
    @param lowestFrequency: The lowest frequency in the filter as absolute pixel value
    @type lowestFrequency: L{float}
    @param highestFrequency: The highest frequency in the filter as absolute pixel value
    @type highestFrequency: L{float} 
    @param bpf: Bandpassfilter C++ object if it is already existing 
    @param smooth: Adjusts the size of gaussian falloff around each band end.
    @return: The bandpass filtered volume, the filter and the filtered volume in fourier space
    @author: Thomas Hrabe
    """

    import pytom_freqweight
    import pytom_volume
    
    if volume.__class__ == pytom_volume.vol:
        from pytom.basic.fourier import fft
        fvolume = fft(volume)
    else:
        fvolume = volume
 
    if not bpf:
        bpf = pytom_freqweight.weight(lowestFrequency,highestFrequency,
                                      fvolume.sizeX(),fvolume.sizeY(),fvolume.sizeZ(),smooth)    

    return filter(fvolume,bpf,fourierOnly)      
예제 #6
0
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
예제 #7
0
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]
예제 #8
0
    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
예제 #9
0
파일: fourier.py 프로젝트: mvanevic/PyTom
def powerspectrum(volume):
    """
    compute power spectrum of a volume
    
    @param volume: input volume
    @type volume: L{pytom_volume.vol}
    @return: power spectrum of vol
    @rtype: L{pytom_volume.vol}

    @author: FF
    """
    from pytom.basic.fourier import fft, ftshift
    from pytom_volume import vol
    from pytom_volume import reducedToFull

    fvol = ftshift(reducedToFull(fft(volume)),inplace=False)
    nx=fvol.sizeX()
    ny=fvol.sizeY()
    nz=fvol.sizeZ()
    ps = vol(nx,ny,nz)
    sf = 1./(nx*ny*nz)

    for ix in range(0,nx):
        for iy in range(0,ny):
            for iz in range(0,nz):
                temp = fvol.getV(ix,iy,iz)
                temp = temp*temp.conjugate()*sf
                ps.setV(float(temp.real),ix,iy,iz)
    return ps
예제 #10
0
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
예제 #11
0
    def test_resize2D(self):
        """
        test re-sizing in Fourier space
        """
        from pytom.basic.transformations import resize
        from pytom_volume import vol
        from pytom.basic.fourier import fft

        dim = 32
        px = 11
        py = 19
        scf = dim * dim
        myVol = vol(dim, dim, 1)
        myVol.setAll(0.)
        myVol.setV(1., px, py, 0)
        #fmyVol = fft(myVol)
        (resizeVol, resizefVol) = resize(volume=myVol,
                                         factor=2.,
                                         interpolation='Fourier')
        resizeVol.write('test1.em')
        ftresizeVol = fft(data=resizeVol)
        for ix in range(resizefVol.sizeX()):
            for iy in range(resizefVol.sizeY()):
                diff = ftresizeVol.getV(
                    ix, iy, 0) - scf * 4 * resizefVol.getV(ix, iy, 0)
                self.assertTrue(expr=abs(diff) < .05,
                                msg="inconsistency FFT/IFFT for magnification")
        (resizeVol, resizefVol) = resize(volume=resizeVol,
                                         factor=.5,
                                         interpolation='Fourier')
        from pytom_volume import variance
        diff = myVol - resizeVol
        self.assertTrue(expr=variance(diff, False) < .0000001,
                        msg="2D image before and after rescales differs")
예제 #12
0
def FSCSum(volume,reference,numberOfBands,wedgeAngle=-1):
    """
    FSCSum: Determines the sum of the Fourier Shell Correlation coefficient for a volume and reference. 
    @param volume: A volume
    @type volume: L{pytom_volume.vol}
    @param reference: A reference of same size as volume
    @type reference: L{pytom_volume.vol}
    @param numberOfBands: Number of bands
    @param wedgeAngle: A optional wedge angle
    @return: The sum FSC coefficient
    @rtype: float  
    @author: Thomas Hrabe   
    """    
    
    from pytom.basic.correlation import bandCC
    import pytom_volume
    from pytom.basic.fourier import fft
    from math import sqrt
    import pytom_freqweight
    result = 0
    numberVoxels = 0
    
    #volume.write('vol.em');
    #reference.write('ref.em');
    fvolume = fft(volume)
    freference = fft(reference)
    numelem = volume.numelem()
    
    fvolume.shiftscale(0,1/float(numelem))
    freference.shiftscale(0,1/float(numelem))

    #print '-----'
    for i in range(numberOfBands):
        #process bandCorrelation
        band = []
        band[0] = i*volume.sizeX()/numberOfBands 
        band[1] = (i+1)*volume.sizeX()/numberOfBands
        
        r = bandCC(fvolume,freference,band)
        cc = r[0]
        #print cc
        result = result + cc
    #print '-----'
    
    return result*(1/float(numberOfBands))
예제 #13
0
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
예제 #14
0
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()
예제 #15
0
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
예제 #16
0
    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
예제 #17
0
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
예제 #18
0
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
예제 #19
0
def highpassFilter(volume,band,smooth=0,fourierOnly=False):   
    """
    highpassFilter:
    @param volume:  The volume filtered
    @type volume: L{pytom_volume.vol}
    @param band: Lower end of band (in pixels)
    @param smooth: Adjusts the size of gaussian falloff around each band end.
    @return: The highpass filtered volume,the filter and the filtered volume in fourier space
    @author: Thomas Hrabe 
    """
    import pytom_freqweight
    import pytom_volume
    
    if volume.__class__ == pytom_volume.vol:
        from pytom.basic.fourier import fft
        fvolume = fft(volume)
    else:
        fvolume = volume
    
    hpf = pytom_freqweight.weight(band,fvolume.sizeX(),fvolume.sizeX(),fvolume.sizeY(),fvolume.sizeZ(),smooth)
       
    return filter(fvolume,hpf,fourierOnly)
예제 #20
0
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
예제 #21
0
    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
예제 #22
0
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]
예제 #23
0
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))
예제 #24
0
파일: average.py 프로젝트: mvanevic/PyTom
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)
예제 #25
0
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
예제 #26
0
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)    
예제 #27
0
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)
예제 #28
0
    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
예제 #29
0
from pytom_volume import *
from pytom.basic.fourier import fft, ifft, ftshift, iftshift

v = read('/fs/home/ychen/matlab/template/binning/temp80SRibosome_bin2.em')
# v = read('/fs/home/ychen/matlab/template/temp80SRibosome.em')

fv = fft(v)

r1 = real(fv)
i1 = imag(fv)

fv2 = fullToReduced(reducedToFull(fv))

r2 = real(fv2)
i2 = imag(fv2)

(r1 - r2).info('')
(i1 - i2).info('')

fv3 = fullToReduced(
    iftshift(ftshift(reducedToFull(fv), inplace=False), inplace=False))

r3 = real(fv3)
i3 = imag(fv3)

(r1 - r3).info('')
(i1 - i3).info('')
예제 #30
0
def frm_correlate(vf,
                  wf,
                  vg,
                  wg,
                  b,
                  max_freq,
                  weights=None,
                  ps=False,
                  denominator1=None,
                  denominator2=None,
                  return_score=True):
    """Calculate the correlation of two volumes as a function of Euler angle.

    Parameters
    ----------
    vf: Volume Nr. 1
        pytom_volume.vol

    wf: Mask of vf in Fourier space.
        pytom.basic.structures.Wedge

    vg: Volume Nr. 2 / Reference
        pytom_volume.vol

    wg: Mask of vg in Fourier space.
        pytom.basic.structures.Wedge

    b: Bandwidth range of spherical harmonics.
       None -> [4, 64]
       List -> [b_min, b_max]
       Integer -> [b, b]

    max_freq: Maximal frequency involved in calculation.
              Integer.

    weights: Obsolete.

    ps: Calculation based on only the power spectrum of two volumes or not.
        Boolean. Default is False.

    denominator1: If the denominator1 is provided or not. If yes, do not have to re-calculate it again.
                  This field is used out of computation effeciency consideration.
                  Default is None, not provided.

    denominator2: If the denominator2 is provided or not. If yes, do not have to re-calculate it again.
                  This field is used out of computation effeciency consideration.
                  Default is None, not provided.

    return_score: Return the correlation score or return the intermediate result (numerator, denominator1, denominator2).
                  Boolean, default is True.

    Returns
    -------
    If return_score is set to True, return the correlation function; otherwise return the intermediate result.
    """
    if not weights:  # weights, not used yet
        weights = [1 for i in xrange(max_freq)]

    from pytom.basic.fourier import fft, ifft, ftshift, iftshift
    from pytom_volume import vol, reducedToFull, abs, real, imag, rescale
    from vol2sf import vol2sf
    from math import log, ceil, pow

    # IMPORTANT!!! Should firstly do the IFFTSHIFT on the volume data (NOT FFTSHIFT since for odd-sized data it matters!),
    # and then followed by the FFT.
    vf = ftshift(reducedToFull(fft(iftshift(vf, inplace=False))),
                 inplace=False)
    vg = ftshift(reducedToFull(fft(iftshift(vg, inplace=False))),
                 inplace=False)

    if ps:  # power spectrum only
        ff = abs(vf)
        ff = real(ff)
        gg = abs(vg)
        gg = real(gg)
    else:  # use spline intepolation on the real/imaginary parts. Can be done better, but now it suffices.
        vfr = real(vf)
        vfi = imag(vf)
        vgr = real(vg)
        vgi = imag(vg)

    numerator = None
    if denominator1 is not None and denominator2 is not None:
        to_calculate = 1
    elif denominator1 is None and denominator2 is not None:
        to_calculate = 2
    else:
        to_calculate = 0

    _last_bw = 0
    # might be a better idea to start from 2 due to the bad interpolation around 0 frequency!
    # this can be better solved by NFFT!
    for r in xrange(1, max_freq + 1):
        # calculate the appropriate bw
        bw = get_adaptive_bw(r, b)

        # construct the wedge masks accordingly
        # now this part has been shifted to Pytom
        # if _last_bw != bw:
        #     # mf = create_wedge_sf(wf[0], wf[1], bw)
        #     # mg = create_wedge_sf(wg[0], wg[1], bw)
        #     mf = wf.toSphericalFunc(bw)
        #     mg = wg.toSphericalFunc(bw)
        mf = wf.toSphericalFunc(bw, r)
        mg = wg.toSphericalFunc(bw, r)

        if ps:
            corr1, corr2, corr3 = sph_correlate_ps(vol2sf(ff, r, bw), mf,
                                                   vol2sf(gg, r, bw), mg,
                                                   to_calculate)
        else:
            corr1, corr2, corr3 = sph_correlate_fourier(
                vol2sf(vfr, r, bw), vol2sf(vfi, r, bw), mf, vol2sf(vgr, r, bw),
                vol2sf(vgi, r, bw), mg, to_calculate)

        if _last_bw != bw:  # size is different, have to do enlarge
            if numerator is None:
                numerator = np.zeros((2 * bw, 2 * bw, 2 * bw), dtype='double')
                if to_calculate == 1:
                    pass
                elif to_calculate == 2:
                    denominator1 = np.zeros((2 * bw, 2 * bw, 2 * bw),
                                            dtype='double')
                else:
                    denominator1 = np.zeros((2 * bw, 2 * bw, 2 * bw),
                                            dtype='double')
                    denominator2 = np.zeros((2 * bw, 2 * bw, 2 * bw),
                                            dtype='double')
            else:
                numerator = enlarge2(numerator)
                if to_calculate == 1:
                    pass
                elif to_calculate == 2:
                    denominator1 = enlarge2(denominator1)
                else:
                    denominator1 = enlarge2(denominator1)
                    denominator2 = enlarge2(denominator2)

        numerator += corr1 * (r**2) * weights[r - 1]
        if to_calculate == 1:
            pass
        elif to_calculate == 2:
            denominator1 += corr2 * (r**2) * weights[r - 1]
        else:
            denominator1 += corr2 * (r**2) * weights[r - 1]
            denominator2 += corr3 * (r**2) * weights[r - 1]

        _last_bw = bw

    if return_score:
        res = numerator / (denominator1 * denominator2)**0.5
        return res
    else:
        return (numerator, denominator1, denominator2)