Ejemplo n.º 1
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
Ejemplo n.º 2
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
Ejemplo n.º 3
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
Ejemplo n.º 4
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
Ejemplo n.º 5
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)