def getDiffResForOverfocus(radii=None, cs=2e-3, volts=120000):
        """
        given Cs and kV, determine the initial resolution where the difference between
        overfocus and underfocus is clearly visible.

        value returned in Angstroms, but radii must be in meters
        """

        if debug is True:
                print "getDiffResForOverfocus()"

        if debug is True:
                apDisplay.printColor("getDiffRes radii: 1/%.2fA --> 1/%.2fA"%(1/radii[1]*1e10, 1/radii[-1]*1e10), "cyan")

        t0 = time.time()
        checkParams(focus1=1.0e-6, focus2=1.0e-6, cs=cs, volts=volts, ampconst=0.0, failParams=False)


        lamb = ctftools.getTEMLambda(volts)
        s = radii
        pi = math.pi

        csgamma = 2*pi*0.25*cs*(lamb**3)*(s**4)
        
        #over/under-focus difference is visible when Cs component is greater than 0.05
        index = numpy.searchsorted(csgamma, 0.03)

        diffres = 1.0/radii[index-1]*1e10

        apDisplay.printColor("Overfocus/Underfocus difference resolution is: 1/%.2fA"%(diffres), "cyan")

        if debug is True:
                print "difference resolution complete in %.9f sec"%(time.time()-t0)
        return diffres
Пример #2
0
def generateCTF1d(radii=None,
                  focus=1.0e-6,
                  cs=2e-3,
                  volts=120000,
                  ampconst=0.07,
                  failParams=False,
                  overfocus=False):
    """
	calculates a CTF function based on the input details

	Use SI units: meters, radians, volts
	Underfocus is postive (defocused) 
	"""
    if debug is True:
        print "generateCTF1dFromRadii()"

    if radii is None:
        radii = generateRadii1d(numpoints=256, pixelsize=1e-10)

    if debug is True:
        apDisplay.printColor(
            "generateCTF radii: 1/%.2fA --> 1/%.2fA" %
            (1 / radii[1] * 1e10, 1 / radii[-1] * 1e10), "cyan")

    t0 = time.time()
    checkParams(focus1=focus,
                focus2=focus,
                cs=cs,
                volts=volts,
                ampconst=ampconst,
                failParams=failParams)

    lamb = ctftools.getTEMLambda(volts)
    s = radii
    pi = math.pi

    if overfocus is True:
        focus = -1.0 * focus

    gamma = -0.5 * pi * cs * (lamb**3) * (s**4) + pi * focus * lamb * (s**2)

    if overfocus is True:
        gamma = -1.0 * gamma

    A = ampconst
    B = math.sqrt(1.0 - ampconst**2)
    prectf = A * numpy.cos(gamma) + B * numpy.sin(gamma)

    ctf = prectf**2

    if debug is True:
        print "generate 1D ctf complete in %.9f sec" % (time.time() - t0)

    return ctf
Пример #3
0
def generateCTF1dACE2(radii=None,
                      focus=1.0e-6,
                      cs=2e-3,
                      volts=120000,
                      ampconst=0.07,
                      failParams=False):
    """
	calculates a CTF function based on the input details

	Use SI units: meters, radians, volts
	Underfocus is postive (defocused) 
	"""
    if debug is True:
        print "generateCTF1dFromRadii()"
    t0 = time.time()
    checkParams(focus1=focus,
                focus2=focus,
                cs=cs,
                volts=volts,
                ampconst=ampconst,
                failParams=failParams)
    minres = 1e10 / radii.min()
    maxres = 1e10 / radii.max()
    if debug is True:
        print "** CTF limits %.1f A -->> %.1fA" % (minres, maxres)
    if maxres < 2.0 or maxres > 50.0:
        apDisplay.printError("CTF limits are incorrect %.1f A -->> %.1fA" %
                             (minres, maxres))

    wavelength = ctftools.getTEMLambda(volts)

    x4 = math.pi / 2.0 * wavelength**3 * cs
    x2 = math.pi * wavelength
    x0 = 1.0 * math.asin(ampconst)  #CORRECT
    if debug is True:
        print "x0 shift %.1f degrees" % (math.degrees(x0))

    radiisq = radii**2

    gamma = (x4 * radiisq**2) + (-focus * x2 * radiisq) + (x0)
    #ctf = -1.0*numpy.cos(gamma) #WRONG
    #ctf = -1.0*numpy.sin(gamma) #CORRECT
    ctf = 1.0 * numpy.sin(gamma)  #MAYBE CORRECT

    if debug is True:
        print "generate 1D ctf complete in %.9f sec" % (time.time() - t0)

    return ctf**2
def generateCTF1d(radii=None, focus=1.0e-6, cs=2e-3, volts=120000, ampconst=0.07, 
                failParams=False, overfocus=False):
        """
        calculates a CTF function based on the input details

        Use SI units: meters, radians, volts
        Underfocus is postive (defocused) 
        """
        if debug is True:
                print "generateCTF1dFromRadii()"

        if radii is None:
                radii = generateRadii1d(numpoints=256, pixelsize=1e-10)

        if debug is True:
                apDisplay.printColor("generateCTF radii: 1/%.2fA --> 1/%.2fA"%(1/radii[1]*1e10, 1/radii[-1]*1e10), "cyan")

        t0 = time.time()
        checkParams(focus1=focus, focus2=focus, cs=cs, volts=volts, ampconst=ampconst, failParams=failParams)

        lamb = ctftools.getTEMLambda(volts)
        s = radii
        pi = math.pi

        if overfocus is True:
                focus = -1.0*focus

        gamma = -0.5*pi*cs*(lamb**3)*(s**4) + pi*focus*lamb*(s**2)

        if overfocus is True:
                gamma = -1.0*gamma

        A = ampconst
        B = math.sqrt(1.0 - ampconst**2)
        prectf = A*numpy.cos(gamma) + B*numpy.sin(gamma)

        ctf = prectf**2

        if debug is True:
                print "generate 1D ctf complete in %.9f sec"%(time.time()-t0)

        return ctf
Пример #5
0
def getDiffResForOverfocus(radii=None, cs=2e-3, volts=120000):
    """
	given Cs and kV, determine the initial resolution where the difference between
	overfocus and underfocus is clearly visible.

	value returned in Angstroms, but radii must be in meters
	"""

    if debug is True:
        print "getDiffResForOverfocus()"

    if debug is True:
        apDisplay.printColor(
            "getDiffRes radii: 1/%.2fA --> 1/%.2fA" %
            (1 / radii[1] * 1e10, 1 / radii[-1] * 1e10), "cyan")

    t0 = time.time()
    checkParams(focus1=1.0e-6,
                focus2=1.0e-6,
                cs=cs,
                volts=volts,
                ampconst=0.0,
                failParams=False)

    lamb = ctftools.getTEMLambda(volts)
    s = radii
    pi = math.pi

    csgamma = 2 * pi * 0.25 * cs * (lamb**3) * (s**4)

    #over/under-focus difference is visible when Cs component is greater than 0.05
    index = numpy.searchsorted(csgamma, 0.03)

    diffres = 1.0 / radii[index - 1] * 1e10

    apDisplay.printColor(
        "Overfocus/Underfocus difference resolution is: 1/%.2fA" % (diffres),
        "cyan")

    if debug is True:
        print "difference resolution complete in %.9f sec" % (time.time() - t0)
    return diffres
def generateCTF1dACE2(radii=None, focus=1.0e-6, cs=2e-3, volts=120000, ampconst=0.07, failParams=False):
        """
        calculates a CTF function based on the input details

        Use SI units: meters, radians, volts
        Underfocus is postive (defocused) 
        """
        if debug is True:
                print "generateCTF1dFromRadii()"
        t0 = time.time()
        checkParams(focus1=focus, focus2=focus, cs=cs, volts=volts, ampconst=ampconst, failParams=failParams)
        minres = 1e10/radii.min()
        maxres = 1e10/radii.max()
        if debug is True:
                print "** CTF limits %.1f A -->> %.1fA"%(minres, maxres)
        if maxres < 2.0 or maxres > 50.0:
                apDisplay.printError("CTF limits are incorrect %.1f A -->> %.1fA"%(minres, maxres))

        wavelength = ctftools.getTEMLambda(volts)

        x4 = math.pi/2.0 * wavelength**3 * cs
        x2 = math.pi * wavelength
        x0 = 1.0*math.asin(ampconst) #CORRECT
        if debug is True:
                print "x0 shift %.1f degrees"%(math.degrees(x0))

        radiisq = radii**2

        gamma = (x4 * radiisq**2) + (-focus * x2 * radiisq) + (x0)
        #ctf = -1.0*numpy.cos(gamma) #WRONG
        #ctf = -1.0*numpy.sin(gamma) #CORRECT
        ctf = 1.0*numpy.sin(gamma) #MAYBE CORRECT

        if debug is True:
                print "generate 1D ctf complete in %.9f sec"%(time.time()-t0)

        return ctf**2
Пример #7
0
    def runRefineCTF(self, imgdata, fftpath):
        ### reset important values
        self.bestres = 1e10
        self.bestellipse = None
        self.bestvalues = {}

        self.volts = imgdata['scope']['high tension']
        self.wavelength = ctftools.getTEMLambda(self.volts)
        ## get value in meters
        self.cs = apInstrument.getCsValueFromSession(
            self.getSessionData()) * 1e-3
        self.ctfvalues = {
            'volts': self.volts,
            'wavelength': self.wavelength,
            'cs': self.cs,
        }

        ### need to get FFT file open and freq of said file
        fftarray = mrc.read(fftpath).astype(numpy.float64)
        self.freq = self.freqdict[fftpath]

        ### convert resolution limit into pixel distance
        fftwidth = fftarray.shape[0]
        maxres = 2.0 / (self.freq * fftwidth)
        if maxres > self.params['reslimit']:
            apDisplay.printWarning(
                "Cannot get requested res %.1fA higher than max Nyquist resolution %.1fA"
                % (self.params['reslimit'], maxres))
            self.params['reslimit'] = math.ceil(maxres)

        limitwidth = int(math.ceil(2.0 /
                                   (self.params['reslimit'] * self.freq)))
        limitwidth = primefactor.getNextEvenPrime(limitwidth)
        requestres = 2.0 / (self.freq * limitwidth)
        if limitwidth > fftwidth:
            apDisplay.printError("Cannot get requested resolution" + (
                " request res %.1fA higher than max res %.1fA for new widths %d > %d"
                % (requestres, maxres, limitwidth, fftwidth)))

        apDisplay.printColor(
            "Requested resolution OK: " +
            (" request res %.1fA less than max res %.1fA with fft widths %d < %d"
             % (requestres, maxres, limitwidth, fftwidth)), "green")
        newshape = (limitwidth, limitwidth)
        fftarray = imagefilter.frame_cut(fftarray, newshape)

        ### spacing parameters
        self.mfreq = self.freq * 1e10
        fftwidth = min(fftarray.shape)
        self.apix = 1.0 / (fftwidth * self.freq)
        self.ctfvalues['apix'] = self.apix

        ### print message
        bestDbValues = ctfdb.getBestCtfByResolution(imgdata)
        if bestDbValues is None:
            apDisplay.printColor(
                "SKIPPING: No CTF values for image %s" %
                (apDisplay.short(imgdata['filename'])), "red")
            self.badprocess = True
            return

        ### skip if resolution > 90.
        if bestDbValues['resolution_50_percent'] > 90.:
            apDisplay.printColor(
                "SKIPPING: No decent CTF values for image %s" %
                (apDisplay.short(imgdata['filename'])), "yellow")
            self.badprocess = True
            return

        self.ctfvalues['amplitude_contrast'] = bestDbValues[
            'amplitude_contrast']

        lowerrad1 = ctftools.getCtfExtrema(
            bestDbValues['defocus1'], self.mfreq, self.cs, self.volts,
            self.ctfvalues['amplitude_contrast'], 1, "valley")
        lowerrad2 = ctftools.getCtfExtrema(
            bestDbValues['defocus2'], self.mfreq, self.cs, self.volts,
            self.ctfvalues['amplitude_contrast'], 1, "valley")
        meanRad = (lowerrad1[0] + lowerrad2[0]) / 2.0

        self.ellipseParams = {
            'a': lowerrad1[0],
            'b': lowerrad2[0],
            'alpha': math.radians(bestDbValues['angle_astigmatism']),
        }
        ellipratio = self.ellipseParams['a'] / self.ellipseParams['b']
        defratio = bestDbValues['defocus2'] / bestDbValues['defocus1']
        print "ellr=%.3f, defr=%.3f, sqrt(defr)=%.3f" % (ellipratio, defratio,
                                                         math.sqrt(defratio))
        self.bestvalues['defocus'] = (bestDbValues['defocus1'] +
                                      bestDbValues['defocus2']) / 2.0

        raddata, PSDarray = self.from2Dinto1D(fftarray)
        lowerbound = numpy.searchsorted(raddata, meanRad * self.freq)
        upperbound = numpy.searchsorted(raddata, 1 / 10.)

        ###
        #	This is the start of the actual program
        ###

        self.refineEllipseLoop(fftarray, lowerbound, upperbound)

        ##==================================
        ## FINISH UP
        ##==================================

        apDisplay.printColor("Finishing up using best found CTF values",
                             "blue")
        self.printBestValues()

        ### take best values and use them
        self.ctfvalues = self.bestvalues
        self.ellipseParams = self.bestellipse

        ### stupid fix, get value in millimeters
        self.ctfvalues['cs'] = apInstrument.getCsValueFromSession(
            self.getSessionData())

        ### translate ellipse into ctf values
        if self.ellipseParams is not None:
            self.ctfvalues['angle_astigmatism'] = math.degrees(
                self.ellipseParams['alpha'])
            ellipratio = self.ellipseParams['a'] / self.ellipseParams['b']
            phi = math.asin(self.ctfvalues['amplitude_contrast'])
            #note: a > b then def1 < def2
            #major axis
            self.ctfvalues['defocus1'] = self.ctfvalues['defocus'] / ellipratio
            #minor axis
            self.ctfvalues['defocus2'] = self.ctfvalues['defocus'] * ellipratio

            defdiff = 1.0 - 2 * self.ctfvalues['defocus'] / (
                self.ctfvalues['defocus1'] + self.ctfvalues['defocus2'])
            print "%.3e --> %.3e,%.3e" % (self.ctfvalues['defocus'],
                                          self.ctfvalues['defocus2'],
                                          self.ctfvalues['defocus1'])
            print defdiff * 100
            if defdiff * 100 > 1:
                apDisplay.printWarning("Large astigmatism")
                #sys.exit(1)
        else:
            ellipratio = 1.0
            self.ctfvalues['angle_astigmatism'] = 0.0
            self.ctfvalues['defocus1'] = self.ctfvalues['defocus']
            self.ctfvalues['defocus2'] = self.ctfvalues['defocus']
            self.badprocess = True
            return

        try:
            if self.ctfvalues['amplitude_contrast'] < self.minAmpCon:
                self.ctfvalues['amplitude_contrast'] = self.minAmpCon
            if self.ctfvalues['amplitude_contrast'] > self.maxAmpCon:
                self.ctfvalues['amplitude_contrast'] = self.maxAmpCon
        except KeyError:
            pass

        if abs(self.ctfvalues['defocus1']) > abs(self.ctfvalues['defocus2']):
            # incorrect, need to shift angle by 90 degrees
            apDisplay.printWarning("|def1| > |def2|, flipping defocus axes")
            tempdef = self.ctfvalues['defocus1']
            self.ctfvalues['defocus1'] = self.ctfvalues['defocus2']
            self.ctfvalues['defocus2'] = tempdef
            self.ctfvalues['angle_astigmatism'] += 90
        # get astig_angle within range -90 < angle <= 90
        while self.ctfvalues['angle_astigmatism'] > 90:
            self.ctfvalues['angle_astigmatism'] -= 180
        while self.ctfvalues['angle_astigmatism'] < -90:
            self.ctfvalues['angle_astigmatism'] += 180

        avgres = self.getResolution(self.ctfvalues['defocus'], raddata,
                                    PSDarray, lowerbound)
        apDisplay.printColor(
            "Final defocus values %.3e -> %.3e, %.3e; ac=%.2f, res=%.1f" %
            (self.ctfvalues['defocus'], self.ctfvalues['defocus1'],
             self.ctfvalues['defocus2'], self.ctfvalues['amplitude_contrast'],
             avgres / 2.0), "green")

        for i in range(10):
            print "===================================="

        print "PREVIOUS VALUES"
        ctfdb.getBestCtfByResolution(imgdata)
        print "CURRENT VALUES"
        defocusratio = self.ctfvalues['defocus2'] / self.ctfvalues['defocus1']
        apDisplay.printColor(
            "def1: %.2e | def2: %.2e | angle: %.1f | ampcontr %.2f | defratio %.3f"
            % (self.ctfvalues['defocus1'], self.ctfvalues['defocus2'],
               self.ctfvalues['angle_astigmatism'],
               self.ctfvalues['amplitude_contrast'], defocusratio), "blue")
        self.printBestValues()
        #ellipratio = self.ellipseParams['a']/self.ellipseParams['b']
        print "ellr=%.3f, defr=%.3f, sqrt(defr)=%.3f" % (
            ellipratio, defocusratio, math.sqrt(defocusratio))
        print "===================================="

        return
        def runRefineCTF(self, imgdata, fftpath):
                ### reset important values
                self.bestres = 1e10
                self.bestellipse = None
                self.bestvalues = {}

                self.volts = imgdata['scope']['high tension']
                self.wavelength = ctftools.getTEMLambda(self.volts)
                ## get value in meters
                self.cs = apInstrument.getCsValueFromSession(self.getSessionData())*1e-3
                self.ctfvalues = {
                        'volts': self.volts,
                        'wavelength': self.wavelength,
                        'cs': self.cs,
                }

                ### need to get FFT file open and freq of said file
                fftarray = mrc.read(fftpath).astype(numpy.float64)
                self.freq = self.freqdict[fftpath]

                ### convert resolution limit into pixel distance
                fftwidth = fftarray.shape[0]
                maxres = 2.0/(self.freq*fftwidth)
                if maxres > self.params['reslimit']:
                        apDisplay.printError("Cannot get requested res %.1fA higher than max res %.1fA"
                                %(maxres, self.params['reslimit']))

                limitwidth = int(math.ceil(2.0/(self.params['reslimit']*self.freq)))
                limitwidth = primefactor.getNextEvenPrime(limitwidth)
                requestres = 2.0/(self.freq*limitwidth)
                if limitwidth > fftwidth:
                        apDisplay.printError("Cannot get requested resolution"
                                +(" request res %.1fA higher than max res %.1fA for new widths %d > %d"
                                %(requestres, maxres, limitwidth, fftwidth)))

                apDisplay.printColor("Requested resolution OK: "
                        +(" request res %.1fA less than max res %.1fA with fft widths %d < %d"
                        %(requestres, maxres, limitwidth, fftwidth)), "green")
                newshape = (limitwidth, limitwidth)
                fftarray = imagefilter.frame_cut(fftarray, newshape)

                ### spacing parameters
                self.mfreq = self.freq*1e10
                fftwidth = min(fftarray.shape)
                self.apix = 1.0/(fftwidth*self.freq)
                self.ctfvalues['apix'] = self.apix

                ### print message
                bestDbValues = ctfdb.getBestCtfByResolution(imgdata)
                if bestDbValues is None:
                        apDisplay.printColor("SKIPPING: No CTF values for image %s"
                                %(apDisplay.short(imgdata['filename'])), "red")
                        self.badprocess = True
                        return

                ### skip if resolution > 90.
                if bestDbValues['resolution_50_percent'] > 90.:
                        apDisplay.printColor("SKIPPING: No decent CTF values for image %s"
                                %(apDisplay.short(imgdata['filename'])), "yellow")
                        self.badprocess = True
                        return

                self.ctfvalues['amplitude_contrast'] = bestDbValues['amplitude_contrast']

                lowerrad1 = ctftools.getCtfExtrema(bestDbValues['defocus1'], self.mfreq, self.cs, self.volts, 
                        self.ctfvalues['amplitude_contrast'], 1, "valley")
                lowerrad2 = ctftools.getCtfExtrema(bestDbValues['defocus2'], self.mfreq, self.cs, self.volts, 
                        self.ctfvalues['amplitude_contrast'], 1, "valley")
                meanRad = (lowerrad1[0] + lowerrad2[0])/2.0

                self.ellipseParams = {
                        'a': lowerrad1[0],
                        'b': lowerrad2[0],
                        'alpha': math.radians(bestDbValues['angle_astigmatism']),
                }
                ellipratio = self.ellipseParams['a']/self.ellipseParams['b']
                defratio = bestDbValues['defocus2']/bestDbValues['defocus1']
                print "ellr=%.3f, defr=%.3f, sqrt(defr)=%.3f"%(ellipratio, defratio, math.sqrt(defratio))
                self.bestvalues['defocus'] = (bestDbValues['defocus1']+bestDbValues['defocus2'])/2.0


                raddata, PSDarray = self.from2Dinto1D(fftarray)
                lowerbound = numpy.searchsorted(raddata, meanRad*self.freq)
                upperbound = numpy.searchsorted(raddata, 1/10.)

                ###
                #       This is the start of the actual program
                ###

                self.refineEllipseLoop(fftarray, lowerbound, upperbound)

                ##==================================
                ## FINISH UP
                ##==================================

                apDisplay.printColor("Finishing up using best found CTF values", "blue")
                self.printBestValues()

                ### take best values and use them
                self.ctfvalues = self.bestvalues
                self.ellipseParams = self.bestellipse

                ### stupid fix, get value in millimeters
                self.ctfvalues['cs'] = apInstrument.getCsValueFromSession(self.getSessionData())

                ### translate ellipse into ctf values
                if self.ellipseParams is not None:
                        self.ctfvalues['angle_astigmatism'] = math.degrees(self.ellipseParams['alpha'])
                        ellipratio = self.ellipseParams['a']/self.ellipseParams['b']
                        phi = math.asin(self.ctfvalues['amplitude_contrast'])
                        #note: a > b then def1 < def2
                        #major axis
                        self.ctfvalues['defocus1'] = self.ctfvalues['defocus']/ellipratio
                        #minor axis
                        self.ctfvalues['defocus2'] = self.ctfvalues['defocus']*ellipratio

                        defdiff = 1.0 - 2*self.ctfvalues['defocus']/(self.ctfvalues['defocus1']+self.ctfvalues['defocus2'])
                        print "%.3e --> %.3e,%.3e"%(self.ctfvalues['defocus'], 
                                        self.ctfvalues['defocus2'], self.ctfvalues['defocus1'])
                        print defdiff*100
                        if defdiff*100 > 1:
                                apDisplay.printWarning("Large astigmatism")
                                #sys.exit(1)
                else:
                        ellipratio = 1.0
                        self.ctfvalues['angle_astigmatism'] = 0.0
                        self.ctfvalues['defocus1'] = self.ctfvalues['defocus']
                        self.ctfvalues['defocus2'] = self.ctfvalues['defocus']

                if self.ctfvalues['amplitude_contrast'] < 0.0:
                        self.ctfvalues['amplitude_contrast'] = 0.0
                if self.ctfvalues['amplitude_contrast'] > self.maxAmpCon:
                        self.ctfvalues['amplitude_contrast'] = self.maxAmpCon

                if abs(self.ctfvalues['defocus1']) > abs(self.ctfvalues['defocus2']):
                        # incorrect, need to shift angle by 90 degrees
                        apDisplay.printWarning("|def1| > |def2|, flipping defocus axes")
                        tempdef = self.ctfvalues['defocus1']
                        self.ctfvalues['defocus1'] = self.ctfvalues['defocus2']
                        self.ctfvalues['defocus2'] = tempdef
                        self.ctfvalues['angle_astigmatism'] += 90
                # get astig_angle within range -90 < angle <= 90
                while self.ctfvalues['angle_astigmatism'] > 90:
                        self.ctfvalues['angle_astigmatism'] -= 180
                while self.ctfvalues['angle_astigmatism'] < -90:
                        self.ctfvalues['angle_astigmatism'] += 180

                avgres = self.getResolution(self.ctfvalues['defocus'], raddata, PSDarray, lowerbound)
                apDisplay.printColor("Final defocus values %.3e -> %.3e, %.3e; ac=%.2f, res=%.1f"
                        %(self.ctfvalues['defocus'], self.ctfvalues['defocus1'], self.ctfvalues['defocus2'],
                        self.ctfvalues['amplitude_contrast'], avgres/2.0), "green")

                for i in range(10):
                        print "===================================="

                print "PREVIOUS VALUES"
                ctfdb.getBestCtfByResolution(imgdata)
                print "CURRENT VALUES"
                defocusratio = self.ctfvalues['defocus2']/self.ctfvalues['defocus1']
                apDisplay.printColor("def1: %.2e | def2: %.2e | angle: %.1f | ampcontr %.2f | defratio %.3f"
                        %(self.ctfvalues['defocus1'], self.ctfvalues['defocus2'], self.ctfvalues['angle_astigmatism'],
                        self.ctfvalues['amplitude_contrast'], defocusratio), "blue")
                self.printBestValues()
                #ellipratio = self.ellipseParams['a']/self.ellipseParams['b']
                print "ellr=%.3f, defr=%.3f, sqrt(defr)=%.3f"%(ellipratio, defocusratio, math.sqrt(defocusratio))
                print "===================================="

                return
Пример #9
0
	def runPhasorCTF(self, imgdata, fftpath):
		### reset important values
		self.bestres = 1e10
		self.bestellipse = None
		self.bestvalues = None
		self.ellipseParams = None
		self.volts = imgdata['scope']['high tension']
		self.wavelength = ctftools.getTEMLambda(self.volts)
		## get value in meters
		self.cs = apInstrument.getCsValueFromSession(self.getSessionData())*1e-3
		self.ctfvalues = {
			'volts': self.volts,
			'wavelength': self.wavelength,
			'cs': self.cs,
		}

		if self.params['astig'] is False:
			self.maxRatio=1.3
		else:
			self.maxRatio=2.0

		### need to get FFT file open and freq of said file
		fftarray = mrc.read(fftpath).astype(numpy.float64)
		self.freq = self.freqdict[fftpath]

		### print message
		ctfdb.getBestCtfByResolution(imgdata)

		### convert resolution limit into pixel distance
		fftwidth = fftarray.shape[0]
		maxres = 2.0/(self.freq*fftwidth)
		if maxres > self.params['reslimit']:
			apDisplay.printError("Cannot get requested res %.1fA higher than max res %.1fA"
				%(maxres, self.params['reslimit']))

		limitwidth = int(math.ceil(2.0/(self.params['reslimit']*self.freq)))
		limitwidth = primefactor.getNextEvenPrime(limitwidth)
		requestres = 2.0/(self.freq*limitwidth)
		if limitwidth > fftwidth:
			apDisplay.printError("Cannot get requested resolution"
				+(" request res %.1fA higher than max res %.1fA for new widths %d > %d"
				%(requestres, maxres, limitwidth, fftwidth)))

		apDisplay.printColor("Requested resolution OK: "
			+(" request res %.1fA less than max res %.1fA with fft widths %d < %d"
			%(requestres, maxres, limitwidth, fftwidth)), "green")
		newshape = (limitwidth, limitwidth)
		fftarray = imagefilter.frame_cut(fftarray, newshape)

		### spacing parameters
		self.mfreq = self.freq*1e10
		fftwidth = min(fftarray.shape)
		self.apix = 1.0/(fftwidth*self.freq)
		self.ctfvalues['apix'] = self.apix

		if self.params['sample'] is 'stain':
			self.ctfvalues['amplitude_contrast'] = 0.14
		else:
			self.ctfvalues['amplitude_contrast'] = 0.07

		###
		#	This is the start of the actual program
		###

		### this is either simple rotational average, 
		### or complex elliptical average with edge find and RANSAC
		raddata, PSDarray = self.from2Dinto1D(fftarray)

		lowerrad = ctftools.getCtfExtrema(self.params['maxdef'], self.mfreq, self.cs, self.volts, 
			self.ctfvalues['amplitude_contrast'], 1, "valley")
		lowerbound = numpy.searchsorted(raddata, lowerrad[0]*self.freq)

		if self.params['sample'] is 'stain':
			upperbound = numpy.searchsorted(raddata, 1/8.)
		else:
			upperbound = numpy.searchsorted(raddata, 1/12.)

		### fun way to get initial defocus estimate
		fitData = self.fitLinearPlus(raddata, PSDarray)
		#lowessFit = lowess.lowess(raddata**2, PSDarray, smoothing=0.6666)

		if self.debug is True:
			from matplotlib import pyplot
			pyplot.clf()
			pyplot.plot(raddata**2, PSDarray)
			pyplot.plot(raddata**2, fitData)
			pyplot.show()

		flatPSDarray = PSDarray-fitData
		flatPSDarray /= numpy.abs(flatPSDarray[lowerbound:upperbound]).max()

		defocus = self.gridSearch(raddata, flatPSDarray, lowerbound)

		#defocus = findroots.estimateDefocus(raddata[lowerbound:upperbound], flatPSDarray[lowerbound:upperbound], 
		#	cs=self.cs, wavelength=self.wavelength,  amp_con=self.ctfvalues['amplitude_contrast'], 
		#	mindef=self.params['mindef'], maxdef=self.params['maxdef'], volts=self.volts)
	
		amplitudecontrast = sinefit.refineAmplitudeContrast(raddata[lowerbound:upperbound]*1e10, defocus, 
			flatPSDarray[lowerbound:upperbound], self.ctfvalues['cs'], self.wavelength, msg=self.debug)
		if amplitudecontrast is not None:
			print "amplitudecontrast", amplitudecontrast
			self.ctfvalues['amplitude_contrast'] = amplitudecontrast
	
		defocus = self.defocusLoop(defocus, raddata, flatPSDarray, lowerbound, upperbound)

		#lowerrad = ctftools.getCtfExtrema(defocus, self.mfreq, self.cs, self.volts, 
		#	self.ctfvalues['amplitude_contrast'], 1, "valley")
		#lowerbound = numpy.searchsorted(raddata, lowerrad[0]*self.freq)

		normPSDarray = self.fullTriSectionNormalize(raddata, PSDarray, defocus)

		defocus = self.defocusLoop(defocus, raddata, normPSDarray, lowerbound, upperbound)

		self.findEllipseLoop(fftarray, lowerbound, upperbound)

		self.refineEllipseLoop(fftarray, lowerbound, upperbound)

		##==================================
		## FINISH UP
		##==================================

		apDisplay.printColor("Finishing up using best found CTF values", "blue")
		self.printBestValues()

		if self.bestvalues is None:
			apDisplay.printColor("No CTF estimate found for this image", "red")	
			self.badprocess = True
			return

		### take best values and use them
		self.ctfvalues = self.bestvalues
		self.ellipseParams = self.bestellipse

		### stupid fix, get value in millimeters
		self.ctfvalues['cs'] = apInstrument.getCsValueFromSession(self.getSessionData())

		### translate ellipse into ctf values
		if self.ellipseParams is not None:
			self.ctfvalues['angle_astigmatism'] = math.degrees(self.ellipseParams['alpha'])
			ellipratio = self.ellipseParams['a']/self.ellipseParams['b']
			phi = math.asin(self.ctfvalues['amplitude_contrast'])
			#note: a > b then def1 < def2
			#major axis
			self.ctfvalues['defocus1'] = self.ctfvalues['defocus']/ellipratio
			#minor axis
			self.ctfvalues['defocus2'] = self.ctfvalues['defocus']*ellipratio

			defdiff = 1.0 - 2*self.ctfvalues['defocus']/(self.ctfvalues['defocus1']+self.ctfvalues['defocus2'])
			print "%.3e --> %.3e,%.3e"%(self.ctfvalues['defocus'], 
					self.ctfvalues['defocus2'], self.ctfvalues['defocus1'])
			print defdiff*100
			if defdiff*100 > 1:
				apDisplay.printWarning("Large astigmatism")
				#sys.exit(1)
		else:
			self.ctfvalues['angle_astigmatism'] = 0.0
			self.ctfvalues['defocus1'] = self.ctfvalues['defocus']
			self.ctfvalues['defocus2'] = self.ctfvalues['defocus']

		if self.ctfvalues['amplitude_contrast'] < 0.0:
			self.ctfvalues['amplitude_contrast'] = 0.0
		if self.ctfvalues['amplitude_contrast'] > self.maxAmpCon:
			self.ctfvalues['amplitude_contrast'] = self.maxAmpCon

		if abs(self.ctfvalues['defocus1']) > abs(self.ctfvalues['defocus2']):
			# incorrect, need to shift angle by 90 degrees
			apDisplay.printWarning("|def1| > |def2|, flipping defocus axes")
			tempdef = self.ctfvalues['defocus1']
			self.ctfvalues['defocus1'] = self.ctfvalues['defocus2']
			self.ctfvalues['defocus2'] = tempdef
			self.ctfvalues['angle_astigmatism'] += 90
		# get astig_angle within range -90 < angle <= 90
		while self.ctfvalues['angle_astigmatism'] > 90:
			self.ctfvalues['angle_astigmatism'] -= 180
		while self.ctfvalues['angle_astigmatism'] < -90:
			self.ctfvalues['angle_astigmatism'] += 180

		avgres = self.getResolution(self.ctfvalues['defocus'], raddata, PSDarray, lowerbound)
		apDisplay.printColor("Final defocus values %.3e -> %.3e, %.3e; ac=%.2f, res=%.1f"
			%(self.ctfvalues['defocus'], self.ctfvalues['defocus1'], self.ctfvalues['defocus2'],
			self.ctfvalues['amplitude_contrast'], avgres/2.0), "green")

		for i in range(10):
			print "===================================="

		print "PREVIOUS VALUES"
		ctfdb.getBestCtfByResolution(imgdata)
		print "CURRENT VALUES"
		defocusratio = self.ctfvalues['defocus2']/self.ctfvalues['defocus1']
		apDisplay.printColor("def1: %.2e | def2: %.2e | angle: %.1f | ampcontr %.2f | defratio %.3f"
			%(self.ctfvalues['defocus1'], self.ctfvalues['defocus2'], self.ctfvalues['angle_astigmatism'],
			self.ctfvalues['amplitude_contrast'], defocusratio), "blue")
		self.printBestValues()
		print "===================================="

		return