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 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
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
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
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
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