예제 #1
0
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
예제 #2
0
파일: ctftools.py 프로젝트: vossman/ctfeval
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
예제 #3
0
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
예제 #4
0
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
예제 #5
0
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
예제 #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
예제 #8
0
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
예제 #10
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
예제 #11
0
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
예제 #12
0
			%(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)