def boxerRotate(imgfile, parttree, outstack, boxsize): """ boxes the particles with expanded size, applies a rotation to particle, reduces boxsize to requested size, and saves them to a imagic file """ # size needed is sqrt(2)*boxsize, using 1.5 to be extra safe bigboxsize = int(math.ceil(1.5*boxsize)) imgarray = mrc.read(imgfile) bigboxedparticles = boxerMemory(imgarray, parttree, bigboxsize) boxedparticles = [] boxshape = (boxsize,boxsize) apDisplay.printMsg("Rotating particles...") for i in range(len(bigboxedparticles)): if i % 10 == 0: sys.stderr.write(".") bigboxpart = bigboxedparticles[i] partdict = parttree[i] ### add 90 degrees because database angle is from x-axis not y-axis angle = partdict['angle']+90.0 rotatepart = ndimage.rotate(bigboxpart, angle=angle, reshape=False, order=1) boxpart = imagefilter.frame_cut(rotatepart, boxshape) boxedparticles.append(boxpart) sys.stderr.write("done\n") apImagicFile.writeImagic(boxedparticles, outstack) return True
def getEllipticalDistanceArray(ellipratio, ellipangle, shape): ## ellip angle is positive toward y-axis if ellipratio < 1: ellipratio = 1.0/ellipratio ellipangle += 90 while ellipangle > 180: ellipangle -= 180 while ellipangle < 0: ellipangle += 180 if debug is True: apDisplay.printColor("ellipangle = %.3f"%(ellipangle), "cyan") bigshape = numpy.array(numpy.array(shape)*math.sqrt(2)/2., dtype=numpy.int)*2 xhalfshape = bigshape[0]/2.0 x = numpy.arange(-xhalfshape, xhalfshape, 1) + 0.5 yhalfshape = bigshape[1]/2.0 y = numpy.arange(-yhalfshape, yhalfshape, 1) + 0.5 xx, yy = numpy.meshgrid(x, y) ### apply ellipse ratio yy = ellipratio*yy radial = xx**2 + yy**2 ### apply ellipse rotation ## ellip angle is positive toward y-axis, which is clockwise, so negative angle radial = scipy.ndimage.interpolation.rotate(radial, angle=-ellipangle, reshape=False, mode='wrap', order=1) radial = imagefilter.frame_cut(radial, shape) if debug is True: print "minimal radial distance", radial.min() radial = numpy.sqrt(radial) return radial
def trimPowerSpectraToOuterResolution(powerspec, outerresolution, freq): """ freq and outerresolution must have same units (e.g., Anstroms or meters) resolution = (# columns) * apix / (pixel distance from center) therefore: pixel distance from center = (# columns) * apix / resolution """ if debug is True: print "trimPowerSpectraToOuterResolution()" imagewidth = powerspec.shape[0] initmaxres = 2.0 / (freq * imagewidth) if debug is True: print "__Image shape %d x %d" % (powerspec.shape[0], powerspec.shape[1]) print "__Frequeny %.3e" % (freq) print "__Resolution request %.3f" % (outerresolution) print "__Init max resolution %.3f" % (initmaxres) if initmaxres > outerresolution: apDisplay.printWarning( "Requested resolution (%.3f) is not available (%.3f)" % (outerresolution, initmaxres)) outerresolution = initmaxres pixellimitradius = min(powerspec.shape[0], powerspec.shape[1]) / 2 else: pixellimitradius = int(math.ceil(1. / (freq * outerresolution))) goodpixellimitradius = primefactor.getNextEvenPrime(pixellimitradius) # If outerresolution input is larger than initmaxres, the way goodpixellimitradius # is calculated above may make the result larger than half the image dimension. while goodpixellimitradius > min(powerspec.shape[0], powerspec.shape[1]) / 2: pixellimitradius -= 2 if debug is True: print "__Recalculate pixel limit dimension with: ", pixellimitradius goodpixellimitradius = primefactor.getNextEvenPrime(pixellimitradius) finalres = 1. / (freq * goodpixellimitradius) if debug is True: print "__Pixel limit dimension: ", goodpixellimitradius print "__Final max resolution %.3f" % (finalres) ### convert to diameter and trim newshape = (goodpixellimitradius * 2, goodpixellimitradius * 2) if debug is True: print "__Trimming image" trimpowerspec = imagefilter.frame_cut(powerspec, newshape) if newshape != trimpowerspec.shape: apDisplay.printError( "shape mismatch for frame_cut (%d,%d) --> (%d,%d) = (%d,%d)" % (powerspec.shape[0], powerspec.shape[1], newshape[0], newshape[1], trimpowerspec.shape[0], trimpowerspec.shape[1])) if debug is True: print "original image size %d x %d" % (powerspec.shape) print "trimmed image size %d x %d" % (trimpowerspec.shape) return trimpowerspec
def trimPowerSpectraToOuterResolution(powerspec, outerresolution, freq): """ freq and outerresolution must have same units (e.g., Anstroms or meters) resolution = (# columns) * apix / (pixel distance from center) therefore: pixel distance from center = (# columns) * apix / resolution """ if debug is True: print "trimPowerSpectraToOuterResolution()" imagewidth = powerspec.shape[0] initmaxres = 2.0/(freq*imagewidth) if debug is True: print "__Image shape %d x %d"%(powerspec.shape[0], powerspec.shape[1]) print "__Frequeny %.3e"%(freq) print "__Resolution request %.3f"%(outerresolution) print "__Init max resolution %.3f"%(initmaxres) if initmaxres > outerresolution: apDisplay.printWarning("Requested resolution (%.3f) is not available (%.3f)" %(outerresolution, initmaxres)) outerresolution = initmaxres pixellimitradius = min(powerspec.shape[0],powerspec.shape[1]) / 2 else: pixellimitradius = int(math.ceil(1./(freq * outerresolution))) goodpixellimitradius = primefactor.getNextEvenPrime(pixellimitradius) # If outerresolution input is larger than initmaxres, the way goodpixellimitradius # is calculated above may make the result larger than half the image dimension. while goodpixellimitradius > min(powerspec.shape[0],powerspec.shape[1])/2: pixellimitradius -= 2 if debug is True: print "__Recalculate pixel limit dimension with: ", pixellimitradius goodpixellimitradius = primefactor.getNextEvenPrime(pixellimitradius) finalres = 1./(freq * goodpixellimitradius) if debug is True: print "__Pixel limit dimension: ", goodpixellimitradius print "__Final max resolution %.3f"%(finalres) ### convert to diameter and trim newshape = (goodpixellimitradius*2, goodpixellimitradius*2) if debug is True: print "__Trimming image" trimpowerspec = imagefilter.frame_cut(powerspec, newshape) if newshape != trimpowerspec.shape: apDisplay.printError("shape mismatch for frame_cut (%d,%d) --> (%d,%d) = (%d,%d)" %(powerspec.shape[0],powerspec.shape[1], newshape[0],newshape[1], trimpowerspec.shape[0],trimpowerspec.shape[1])) if debug is True: print "original image size %d x %d"%(powerspec.shape) print "trimmed image size %d x %d"%(trimpowerspec.shape) return trimpowerspec
def mergeImageStackIntoBigStack(self, imgstackfile, imgdata): t0 = time.time() apDisplay.printMsg("filtering particles and adding to stack") # if applying a boxmask, write to a temporary file before adding to main stack bigimgstack = os.path.join(self.params['rundir'], self.params['single']) if self.params['boxmask'] is not None: bigimgstack = os.path.splitext(imgstackfile)[0]+"-premask.hed" ### here is the craziness ### step 1: read imgstackfile into memory imgstackmemmap = imagic.read(imgstackfile) ### when only particle is read it defaults to a 2D array instead of 3D array if len(imgstackmemmap.shape) < 3: imgstackmemmap = imgstackmemmap.reshape(1, imgstackmemmap.shape[0], imgstackmemmap.shape[1]) if self.params['debug'] is True: print "imgstackmemmap.shape", imgstackmemmap.shape apix = self.params['apix'] #apDatabase.getPixelSize(imgdata) boxshape = (self.boxsize, self.boxsize) processedParticles = [] for particle in imgstackmemmap: ### step 2: filter particles ### high / low pass filtering #if self.params['pixlimit']: # particle = imagefilter.pixelLimitFilter(particle, self.params['pixlimit']) if self.params['lowpass']: particle = imagefilter.lowPassFilter(particle, apix=apix, radius=self.params['lowpass']) if self.params['highpass']: particle = imagefilter.highPassFilter2(particle, self.params['highpass'], apix=apix) ### unless specified, invert the images if self.params['inverted'] is True: particle = -1.0 * particle if particle.shape != boxshape: if self.boxsize <= particle.shape[0] and self.boxsize <= particle.shape[1]: particle = imagefilter.frame_cut(particle, boxshape) else: apDisplay.printError("particle shape (%dx%d) is smaller than boxsize (%d)" %(particle.shape[0], particle.shape[1], self.boxsize)) ### step 3: normalize particles #self.normoptions = ('none', 'boxnorm', 'edgenorm', 'rampnorm', 'parabolic') #normalizemethod if self.params['normalizemethod'] == 'boxnorm': particle = imagenorm.normStdev(particle) elif self.params['normalizemethod'] == 'edgenorm': particle = imagenorm.edgeNorm(particle) elif self.params['normalizemethod'] == 'rampnorm': particle = imagenorm.rampNorm(particle) elif self.params['normalizemethod'] == 'parabolic': particle = imagenorm.parabolicNorm(particle) ### step 4: decimate/bin particles if specified ### binning is last, so we maintain most detail and do not have to deal with binned apix if self.params['bin'] > 1: particle = imagefun.bin2(particle, self.params['bin']) #from scipy.misc import toimage #toimage(particle).show() processedParticles.append(particle) ### step 5: merge particle list with larger stack apImagicFile.appendParticleListToStackFile(processedParticles, bigimgstack, msg=self.params['debug']) #remove original image stack from memory del imgstackmemmap del processedParticles t0 = time.time() # if applying boxmask, now mask the particles & append to stack if self.params['boxmask'] is not None: # normalize particles before boxing, since zeros in mask # can affect subsequent processing if not properly normalized apEMAN.executeEmanCmd("proc2d %s %s edgenorm inplace"%(bigimgstack,bigimgstack),showcmd=False) imgstack = apImagicFile.readImagic(bigimgstack, msg=False) maskstack = apImagicFile.readImagic(self.params['boxmaskf'],msg=False) for i in range(len(imgstack['images'])): imgstack['images'][i]*=maskstack['images'][i] maskedpartstack = os.path.splitext(imgstackfile)[0]+"-aftermask.hed" apImagicFile.writeImagic(imgstack['images'], maskedpartstack) bigimgstack = os.path.join(self.params['rundir'], self.params['single']) apEMAN.executeEmanCmd("proc2d %s %s flip"%(maskedpartstack,bigimgstack)) ### count particles bigcount = apFile.numImagesInStack(bigimgstack, self.boxsize/self.params['bin']) imgcount = apFile.numImagesInStack(imgstackfile, self.boxsize) ### append to particle log file partlogfile = os.path.join(self.params['rundir'], self.timestamp+"-particles.info") f = open(partlogfile, 'a') for i in range(imgcount): partnum = self.particleNumber + i + 1 line = str(partnum)+'\t'+os.path.join(imgdata['session']['image path'], imgdata['filename']+".mrc") f.write(line+"\n") f.close() self.mergestacktimes.append(time.time()-t0) return bigcount
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 findAstigmatism(fftarray, freq, defocus, resolution, ctfvalues, peakNum=1): """ find the astigmatism from a radial 1D estimate of the defocus """ #searchError = resolution/100. extrema = ctftools.getCtfExtrema(defocus, freq*1e10, ctfvalues['cs'], ctfvalues['volts'], ctfvalues['amplitude_contrast'], numzeros=peakNum*2+1, zerotype="all") if len(extrema) < 2*peakNum: return None minEdgeRadius = int(math.ceil(extrema[peakNum-1])) #first peak maxEdgeRadius = int(math.ceil(extrema[peakNum])) #second peak newshape = (maxEdgeRadius*2, maxEdgeRadius*2) print "newshape",newshape fftcenter = copy.deepcopy(imagefilter.frame_cut(fftarray, newshape)) showImage(fftcenter) shape = fftcenter.shape ## create a grid of distance from the center xhalfshape = shape[0]/2.0 x = numpy.arange(-xhalfshape, xhalfshape, 1) + 0.5 yhalfshape = shape[1]/2.0 y = numpy.arange(-yhalfshape, yhalfshape, 1) + 0.5 xx, yy = numpy.meshgrid(x, y) radialArray = xx**2 + yy**2 - 0.5 #radialArray = numpy.sqrt(radial) maxVal = fftcenter.max()*2 minVal = fftcenter.min() if debug is True: fftcenter = numpy.where(radialArray > maxEdgeRadius**2, maxVal, fftcenter) showImage(fftcenter) fftcenter = numpy.where(radialArray < minEdgeRadius**2, maxVal, fftcenter) showImage(fftcenter) angleArray = numpy.arctan2(-yy,xx) numSteps = 360 angleArray += math.pi angleArray /= 2*math.pi angleArray *= numSteps angleArray = numpy.asarray(angleArray, dtype=numpy.uint16) showImage(angleArray) dataIntegers = numpy.array(range(numSteps)) xyData = numpy.array( scipy.ndimage.measurements.minimum_position( fftcenter, angleArray, dataIntegers)) if debug is True: fftcenter[xyData[:,0], xyData[:,1]] = maxVal*3 showImage(fftcenter) ellipseParams = ellipse.totalLeastSquareEllipse(xyData, center=(xhalfshape, yhalfshape)) if ellipseParams is None: return None ellipse.printParamsDict(ellipseParams) if debug is True: numPoints = int(math.pi*(ellipseParams['a']+ellipseParams['b'])) ellPoints = ellipse.generate_ellipse(ellipseParams['a'], ellipseParams['b'], ellipseParams['alpha'], center=ellipseParams['center'], numpoints=numPoints, integers=True) fftcenter[ellPoints[:,0], ellPoints[:,1]] += maxVal showImage(fftcenter) return ellipseParams
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
%(fieldsize, count, apDisplay.timeString(time.time()-t0))) return poweravg, freq #=================== #=================== #=================== if __name__ == "__main__": a = mrc.read("/home/vosslab/test.mrc") a = imagefilter.planeRegression(a) fullpower = imagefun.power(a) #imagestat.printImageInfo(a) t0 = time.time() x = numpy.arange(6, 13) N = 2**x print N for n in N: print "=====================================" b = power(a, n) b = imagefilter.frame_cut(b, numpy.array(b.shape)/2) imagefile.arrayToPng(b, "%04d-field.png"%(n)) imagestat.printImageInfo(b) bin = int(round(2**12/n)) b = imagefun.bin2(fullpower, bin) b = imagefilter.frame_cut(b, numpy.array(b.shape)/2) imagefile.arrayToPng(b, "%04d-binned.png"%(n)) imagestat.printImageInfo(b) print "complete in %s"%(apDisplay.timeString(time.time()-t0)) #imagestat.printImageInfo(b)