def runAceCorrect(imgdict,params):
	imgname = imgdict['filename']
	imgpath = os.path.join(imgdict['session']['image path'], imgname+'.mrc')

	voltage = (imgdict['scope']['high tension'])
	apix    = apDatabase.getPixelSize(imgdict)

	ctfvalues = ctfdb.getBestCtfByResolution(imgdata)
	conf = ctfdb.calculateConfidenceScore(bestctfvalue)

	ctdimname = imgname
	ctdimpath = os.path.join(params['rundir'],ctdimname)
	print "Corrected Image written to " + ctdimpath

	#pdb.set_trace()
	acecorrectcommand=("ctfcorrect1('%s', '%s', '%.32f', '%.32f', '%f', '%f', '%f');" % \
		(imgpath, ctdimpath, ctfvalues['defocus1'], ctfvalues['defocus2'], -ctfvalues['angle_astigmatism'], voltage, apix))
	print acecorrectcommand
	try:
		matlab = pymat.open("matlab -nosplash")
	except:
		apDisplay.environmentError()
		raise
	pymat.eval(matlab, acecorrectcommand)
	pymat.close(matlab)

	return
	def reprocessImage(self, imgdata):
		"""
		Returns
		True, if an image should be reprocessed
		False, if an image was processed and should NOT be reprocessed
		None, if image has not yet been processed
		e.g. a confidence less than 80%
		"""
		if self.params['reprocess'] is None:
			return True

		ctfvalue = ctfdb.getBestCtfByResolution(imgdata, msg=False)

		if ctfvalue is None:
			return True

		if conf > self.params['reprocess']:
			# small, unbinned images can give same defocus values for 1 & 2:
			if self.params['bin'] == 1 or ctfvalue['defocus1'] != ctfvalue['defocus2']:
				return False
		return True
        def reprocessImage(self, imgdata):
                """
                Returns
                True, if an image should be reprocessed
                False, if an image was processed and should NOT be reprocessed
                None, if image has not yet been processed
                e.g. a confidence less than 80%
                """
                if self.params['reprocess'] is None:
                        return True

                ctfvalue = ctfdb.getBestCtfByResolution(imgdata, msg=False)

                if ctfvalue is None:
                        return None

                avgres = (ctfvalue['resolution_80_percent'] + ctfvalue['resolution_50_percent'])/2.0

                if avgres < self.params['reprocess']:
                        return False
                return True
Example #4
0
    def reprocessImage(self, imgdata):
        """
		Returns
		True, if an image should be reprocessed
		False, if an image was processed and should NOT be reprocessed
		None, if image has not yet been processed
		e.g. a confidence less than 80%
		"""
        if self.params['reprocess'] is None:
            return True

        ctfvalue = ctfdb.getBestCtfByResolution(imgdata, msg=False)

        if ctfvalue is None:
            return None

        avgres = (ctfvalue['resolution_80_percent'] +
                  ctfvalue['resolution_50_percent']) / 2.0

        if avgres < self.params['reprocess']:
            return False
        return True
Example #5
0
    def reprocessImage(self, imgdata):
        """
		Returns
		True, if an image should be reprocessed
		False, if an image was processed and should NOT be reprocessed
		None, if image has not yet been processed
		e.g. a confidence less than 80%
		"""
        if self.params['reprocess'] is None:
            return True

        ctfvalue = ctfdb.getBestCtfByResolution(imgdata, msg=False)

        if ctfvalue is None:
            return True

        if conf > self.params['reprocess']:
            # small, unbinned images can give same defocus values for 1 & 2:
            if self.params['bin'] == 1 or ctfvalue['defocus1'] != ctfvalue[
                    'defocus2']:
                return False
        return True
    def processImage(self, imgdata):
        """
                time ./ctffind3.exe << eof
                micrograph.mrc
                montage.pow
                2.0, 200.0, 0.07, 60000, 7.0, 2 #! CS[mm], HT[kV], AmpCnst, XMAG, DStep[um], PAve
                128, 200.0, 8.0, 5000.0, 40000.0, 5000.0 #! Box, ResMin[A], ResMax[A], dFMin[A], dFMax[A], FStep
                eof

                CARD 1: Input file name for image
                CARD 2: Output file name to check result
                CARD 3: CS[mm], HT[kV], AmpCnst, XMAG, DStep[um],PAve
                CARD 4: Box, ResMin[A], ResMax[A], dFMin[A], dFMax[A], FStep,  dAst[A]
                CTFTILT also asks for TiltA[deg], TiltR[deg] at CARD4

                The output image file to check the result of the fitting
                shows the filtered average power spectrum of the input
                image in one half, and the fitted CTF (squared) in the
                other half. The two halves should agree very well for a
                successful fit.

                CS: Spherical aberration coefficient of the objective in mm
                HT: Electron beam voltage in kV
                AmpCnst: Amount of amplitude contrast (fraction). For ice
                        images 0.07, for negative stain about 0.15.
                XMAG: Magnification of original image
                DStep: Pixel size on scanner in microns, or apix*mag/10000
                PAve: Pixel averaging (PAve x PAve) for input image

                Box: Tile size. The program divides the image into square
                        tiles and calculates the average power spectrum. Tiles
                        with a significantly higher or lower variance are
                        excluded; these are parts of the image which are unlikely
                        to contain useful information (beam edge, film number
                        etc). IMPORTANT: Box must have a even pixel dimensions.
                ResMin: Low resolution end of data to be fitted.
                ResMaX: High resolution end of data to be fitted.
                dFMin: Starting defocus value for grid search in Angstrom.
                        Positive values represent an underfocus. The program
                        performs a systematic grid search of defocus values
                        and astigmatism before fitting a CTF to machine
                        precision.
                dFMax: End defocus value for grid search in Angstrom.
                FStep: Step width for grid search in Angstrom.
                dAst: An additional parameter, dAst, was added to CARD 4 to restrain 
                        the amount of astigmatism in the CTF fit. This makes the 
                        fitting procedure more robust, especially in cases where 
                        the Thon rings are not easily visible.
                TiltA: guessed tilt angle
                TiltR: angular range for initial coarse search 
                """

        #get Defocus in Angstroms
        self.ctfvalues = {}
        nominal = abs(imgdata['scope']['defocus'] * -1.0e10)
        ctfvalue = ctfdb.getBestCtfByResolution(imgdata)
        if ctfvalue is not None:
            bestdef = abs(ctfvalue['defocus1'] +
                          ctfvalue['defocus2']) / 2.0 * 1.0e10
        else:
            bestdef = nominal
        if ctfvalue is not None and self.params['bestdb'] is True:
            bestampcontrast = ctfvalue['amplitude_contrast']
            beststigdiff = abs(ctfvalue['defocus1'] -
                               ctfvalue['defocus2']) * 1e10
        else:
            bestampcontrast = self.params['amp' + self.params['medium']]
            beststigdiff = self.params['dast']
        # dstep is the physical detector pixel size
        dstep = None
        if 'camera' in imgdata and imgdata['camera'] and imgdata['camera'][
                'pixel size']:
            dstep = imgdata['camera']['pixel size']['x']
        if dstep is None:
            dstep = apDatabase.getPixelSize(
                imgdata) * imgdata['scope']['magnification'] / 10000.0
            dstep /= 1e6
        dstep = float(dstep)
        mpixelsize = apDatabase.getPixelSize(imgdata) * 1e-10
        xmag = dstep / mpixelsize
        apDisplay.printMsg("Xmag=%d, dstep=%.2e, mpix=%.2e" %
                           (xmag, dstep, mpixelsize))
        inputparams = {
            'orig':
            os.path.join(imgdata['session']['image path'],
                         imgdata['filename'] + ".mrc"),
            'input':
            apDisplay.short(imgdata['filename']) + ".mrc",
            'output':
            apDisplay.short(imgdata['filename']) + "-pow.mrc",
            'cs':
            self.params['cs'],
            'kv':
            imgdata['scope']['high tension'] / 1000.0,
            'ampcnst':
            bestampcontrast,
            'xmag':
            xmag,
            'dstep':
            dstep * 1e6,
            'pixavg':
            self.params['bin'],
            'box':
            self.params['fieldsize'],
            'resmin':
            self.params['resmin'],
            'resmax':
            self.params['resmax'],
            'defstep':
            self.params['defstep'],  #round(defocus/32.0, 1),
            'dast':
            beststigdiff,
        }
        defrange = self.params['defstep'] * self.params[
            'numstep']  ## do 25 steps in either direction
        inputparams['defmin'] = round(bestdef - defrange, 1)  #in meters
        if inputparams['defmin'] < 0:
            apDisplay.printWarning("Defocus minimum is less than zero")
            inputparams['defmin'] = inputparams['defstep']
        inputparams['defmax'] = round(bestdef + defrange, 1)  #in meters
        apDisplay.printColor(
            "Defocus search range: %d A to %d A (%.2f to %.2f um)" %
            (inputparams['defmin'], inputparams['defmax'],
             inputparams['defmin'] * 1e-4, inputparams['defmax'] * 1e-4),
            "cyan")
        ### create local link to image
        if not os.path.exists(inputparams['input']):
            cmd = "ln -s " + inputparams['orig'] + " " + inputparams[
                'input'] + "\n"
            proc = subprocess.Popen(cmd, shell=True)
            proc.wait()

        ### make standard input for ctf estimation
        line1cmd = inputparams['input'] + "\n"
        line2cmd = inputparams['output'] + "\n"
        line3cmd = (str(inputparams['cs']) + "," + str(inputparams['kv']) +
                    "," + str(inputparams['ampcnst']) + "," +
                    str(inputparams['xmag']) + "," +
                    str(inputparams['dstep']) + "," +
                    str(inputparams['pixavg']) + "\n")
        line4cmd = (str(inputparams['box']) + "," +
                    str(inputparams['resmin']) + "," +
                    str(inputparams['resmax']) + "," +
                    str(inputparams['defmin']) + "," +
                    str(inputparams['defmax']) + "," +
                    str(inputparams['defstep']) + "," +
                    str(inputparams['dast']))

        ### additional ctftilt parameters
        if self.params['ctftilt'] is True:
            tiltang = apDatabase.getTiltAngleDeg(imgdata)
            line4cmd += ("," + str(tiltang) + ",10")
        line4cmd += "\n"

        if os.path.isfile(inputparams['output']):
            # program crashes if this file exists
            apFile.removeFile(inputparams['output'])

        t0 = time.time()
        apDisplay.printMsg("running ctf estimation at " + time.asctime())
        ctfproglog = os.path.join(
            self.logdir,
            os.path.splitext(imgdata['filename'])[0] + "-ctfprog.log")
        logf = open(ctfproglog, "w")
        ctfprogproc = subprocess.Popen(self.ctfprgmexe,
                                       shell=True,
                                       stdin=subprocess.PIPE,
                                       stdout=logf)
        apDisplay.printColor(self.ctfprgmexe, "magenta")
        apDisplay.printColor(line1cmd.strip(), "magenta")
        apDisplay.printColor(line2cmd.strip(), "magenta")
        apDisplay.printColor(line3cmd.strip(), "magenta")
        apDisplay.printColor(line4cmd.strip(), "magenta")
        ctfprogproc.stdin.write(line1cmd)
        ctfprogproc.stdin.write(line2cmd)
        ctfprogproc.stdin.write(line3cmd)
        ctfprogproc.stdin.write(line4cmd)
        ctfprogproc.communicate()
        logf.close()

        apDisplay.printMsg("ctf estimation completed in " +
                           apDisplay.timeString(time.time() - t0))

        #apFile.removeFile(inputparams['input'])

        ### parse ctf estimation output
        self.ctfvalues = {}
        logf = open(ctfproglog, "r")

        ## ctffind & ctftilt have diff # values
        numvals = 6
        if self.params['ctftilt'] is True:
            numvals = 8
        for line in logf:
            sline = line.strip()
            if sline[-12:] == "Final Values":
                #print sline
                if '**********' in sline:
                    sline = re.sub('**********', ' **********', sline)
                bits = sline.split()
                if len(bits) != numvals:
                    apDisplay.printError("wrong number of values in " +
                                         str(bits))
                for i, bit in enumerate(bits[0:(numvals - 2)]):
                    bits[i] = float(bit)
                self.ctfvalues = {
                    'defocus1':
                    float(bits[0]) * 1e-10,
                    'defocus2':
                    float(bits[1]) * 1e-10,
                    # WARNING: this is the negative of the direct result
                    'angle_astigmatism':
                    float(bits[2]),
                    'amplitude_contrast':
                    inputparams['ampcnst'],
                    'cross_correlation':
                    float(bits[numvals - 3]),
                    'nominal':
                    nominal * 1e-10,
                    'defocusinit':
                    bestdef * 1e-10,
                    'cs':
                    self.params['cs'],
                    'volts':
                    imgdata['scope']['high tension'],
                    'confidence':
                    float(bits[numvals - 3]),
                    'confidence_d':
                    round(math.sqrt(abs(float(bits[numvals - 3]))), 5)
                }
                if self.params['ctftilt'] is True:
                    self.ctfvalues['tilt_axis_angle'] = float(bits[3])
                    self.ctfvalues['tilt_angle'] = float(bits[4])

        ### write to log file
        f = open("ctfvalues.log", "a")
        f.write("=== " + imgdata['filename'] + " ===\n")
        line1 = ("nominal=%.1e, bestdef=%.1e," %
                 (self.ctfvalues['nominal'], self.ctfvalues['defocusinit']))
        if self.params['ctftilt'] is True:
            self.ctfvalues['origtiltang'] = tiltang
            line1 += " tilt=%.1f," % tiltang
        apDisplay.printMsg(line1)
        f.write(line1)
        line2 = (
            "def_1=%.1e, def_2=%.1e, astig_angle=%.1f, cross_corr=%.3f,\n" %
            (self.ctfvalues['defocus1'], self.ctfvalues['defocus2'],
             self.ctfvalues['angle_astigmatism'],
             self.ctfvalues['cross_correlation']))
        if self.params['ctftilt'] is True:
            line2 += ("tilt_angle=%.1f, tilt_axis_angle=%.1f,\n" %
                      (self.ctfvalues['tilt_angle'],
                       self.ctfvalues['tilt_axis_angle']))
        apDisplay.printMsg(line2)
        f.write(line2)
        f.close()

        #convert powerspectra to JPEG
        outputjpgbase = os.path.basename(
            os.path.splitext(inputparams['output'])[0] + ".jpg")
        self.lastjpg = outputjpgbase
        outputjpg = os.path.join(self.powerspecdir, self.lastjpg)
        powspec = apImage.mrcToArray(inputparams['output'])
        apImage.arrayToJpeg(powspec, outputjpg)
        shutil.move(inputparams['output'],
                    os.path.join(self.powerspecdir, inputparams['output']))
        self.ctfvalues['graph1'] = outputjpg

        #apFile.removeFile(inputparams['input'])

        return
	def processImage(self, imgdata):
		"""
		time ./ctffind3.exe << eof
		micrograph.mrc
		montage.pow
		2.0, 200.0, 0.07, 60000, 7.0, 2 #! CS[mm], HT[kV], AmpCnst, XMAG, DStep[um], PAve
		128, 200.0, 8.0, 5000.0, 40000.0, 5000.0 #! Box, ResMin[A], ResMax[A], dFMin[A], dFMax[A], FStep
		eof

		CARD 1: Input file name for image
		CARD 2: Output file name to check result
		CARD 3: CS[mm], HT[kV], AmpCnst, XMAG, DStep[um],PAve
		CARD 4: Box, ResMin[A], ResMax[A], dFMin[A], dFMax[A], FStep,  dAst[A]
		CTFTILT also asks for TiltA[deg], TiltR[deg] at CARD4

		The output image file to check the result of the fitting
		shows the filtered average power spectrum of the input
		image in one half, and the fitted CTF (squared) in the
		other half. The two halves should agree very well for a
		successful fit.

		CS: Spherical aberration coefficient of the objective in mm
		HT: Electron beam voltage in kV
		AmpCnst: Amount of amplitude contrast (fraction). For ice
			images 0.07, for negative stain about 0.15.
		XMAG: Magnification of original image
		DStep: Pixel size on scanner in microns, or apix*mag/10000
		PAve: Pixel averaging (PAve x PAve) for input image

		Box: Tile size. The program divides the image into square
			tiles and calculates the average power spectrum. Tiles
			with a significantly higher or lower variance are
			excluded; these are parts of the image which are unlikely
			to contain useful information (beam edge, film number
			etc). IMPORTANT: Box must have a even pixel dimensions.
		ResMin: Low resolution end of data to be fitted.
		ResMaX: High resolution end of data to be fitted.
		dFMin: Starting defocus value for grid search in Angstrom.
			Positive values represent an underfocus. The program
			performs a systematic grid search of defocus values
			and astigmatism before fitting a CTF to machine
			precision.
		dFMax: End defocus value for grid search in Angstrom.
		FStep: Step width for grid search in Angstrom.
		dAst: An additional parameter, dAst, was added to CARD 4 to restrain 
			the amount of astigmatism in the CTF fit. This makes the 
			fitting procedure more robust, especially in cases where 
			the Thon rings are not easily visible.
		TiltA: guessed tilt angle
		TiltR: angular range for initial coarse search 
		"""

		#get Defocus in Angstroms
		self.ctfvalues = {}
		if self.params['nominal'] is not None:
			nominal = abs(self.params['nominal']*1e4)
		else:
			nominal = abs(imgdata['scope']['defocus']*-1.0e10)
		ctfvalue = ctfdb.getBestCtfByResolution(imgdata)
		if ctfvalue is not None:
			"""
			## CTFFIND V3.5 (7-March-2012) prefers the smaller of the two values for astigmatic images
			I found that say you have an image with 1.1um and 1.5um defocus astigmatism. If you give 
			CTFFIND the average value of 1.3um for the defocus and 0.4um astig (dast) then it will 
			try to fit 1.3um and 1.8um, so you need to give it the minimum value (1.1um) for it to 
			fit 1.1um and 1.5um.
			"""
			bestdef = min(ctfvalue['defocus1'],ctfvalue['defocus2'])*1.0e10
		else:
			bestdef = nominal
	
		if ctfvalue is not None and self.params['bestdb'] is True:
			bestampcontrast = round(ctfvalue['amplitude_contrast'],3)
			beststigdiff = round(abs(ctfvalue['defocus1'] - ctfvalue['defocus2'])*1e10,1)
		else:
			bestampcontrast = self.params['amp'+self.params['medium']]
			beststigdiff = self.params['dast']

		if ctfvalue is not None and self.params['bestdb'] is True:
			### set res max from resolution_80_percent
			gmean = (ctfvalue['resolution_80_percent']*ctfvalue['resolution_50_percent']*self.params['resmax'])**(1/3.)
			if gmean < self.params['resmin']:
				# replace only if valid Issue #3291, #3547     
				self.params['resmax'] = round(gmean,2)
				apDisplay.printColor("Setting resmax to the geometric mean of resolution values", "purple")

		# dstep is the physical detector pixel size
		dstep = None
		if 'camera' in imgdata and imgdata['camera'] and imgdata['camera']['pixel size']:
			dstep = imgdata['camera']['pixel size']['x']
		if dstep is None:
			dstep = apDatabase.getPixelSize(imgdata)*imgdata['scope']['magnification']/10000.0
			dstep /=1e6
		dstep = float(dstep)
		mpixelsize = apDatabase.getPixelSize(imgdata)*1e-10
		if self.params['apix_man'] is not None:
			mpixelsize = self.params['apix_man']*1e-10
		xmag = dstep / mpixelsize
		apDisplay.printMsg("Xmag=%d, dstep=%.2e, mpix=%.2e"%(xmag, dstep, mpixelsize))
		inputparams = {
			'orig': os.path.join(imgdata['session']['image path'], imgdata['filename']+".mrc"),
			'input': apDisplay.short(imgdata['filename'])+".mrc",
			'output': apDisplay.short(imgdata['filename'])+"-pow.mrc",

			'cs': self.params['cs'],
			'kv': imgdata['scope']['high tension']/1000.0,
			'ampcnst': bestampcontrast,
			'xmag': xmag,
			'dstep': dstep*1e6,
			'pixavg': self.params['bin'],

			'box': self.params['fieldsize'],
			'resmin': self.params['resmin'],
			'resmax': self.params['resmax'],
			'defstep': self.params['defstep'], #round(defocus/32.0, 1),
			'dast': beststigdiff,
		}
		defrange = self.params['defstep'] * self.params['numstep'] ## do 25 steps in either direction
		inputparams['defmin']= round(bestdef-defrange, 1) #in meters
		if inputparams['defmin'] < 0:
			apDisplay.printWarning("Defocus minimum is less than zero")
			inputparams['defmin'] = inputparams['defstep']
		inputparams['defmax']= round(bestdef+defrange, 1) #in meters
		apDisplay.printColor("Defocus search range: %d A to %d A (%.2f to %.2f um)"
			%(inputparams['defmin'], inputparams['defmax'], 
			inputparams['defmin']*1e-4, inputparams['defmax']*1e-4), "cyan")

		### secondary lock check right before it starts on the real part
		if self.params['parallel'] and os.path.isfile(apDisplay.short(imgdata['filename'])+".mrc"):
			# This is a secondary image lock check, checking the first output of the process.
			# It alone is not good enough
			apDisplay.printWarning('Some other parallel process is working on the same image. Skipping')
			return
		### create local link to image
		if not os.path.exists(inputparams['input']):
			os.symlink(inputparams['orig'], inputparams['input'])

		### make standard input for ctf estimation
		line1cmd = inputparams['input']+"\n"
		line2cmd = inputparams['output']+"\n"
		line3cmd = (
			str(inputparams['cs'])+","
			+ str(inputparams['kv'])+","
			+ str(inputparams['ampcnst'])+","
			+ str(inputparams['xmag'])+","
			+ str(inputparams['dstep'])+","
			+ str(inputparams['pixavg'])+"\n")
		line4cmd = (
			str(inputparams['box'])+","
			+ str(inputparams['resmin'])+","
			+ str(inputparams['resmax'])+","
			+ str(inputparams['defmin'])+","
			+ str(inputparams['defmax'])+","
			+ str(inputparams['defstep'])+","
			+ str(inputparams['dast']))

		### additional ctftilt parameters
		if self.params['ctftilt'] is True:
			tiltang = apDatabase.getTiltAngleDeg(imgdata)
			line4cmd += (","+str(tiltang)+",10")
		line4cmd += "\n"

		if os.path.isfile(inputparams['output']):
			# program crashes if this file exists
			apFile.removeFile(inputparams['output'])

		t0 = time.time()
		apDisplay.printMsg("running ctf estimation at "+time.asctime())
		ctfproglog = os.path.join(self.logdir, os.path.splitext(imgdata['filename'])[0]+"-ctfprog.log")
		logf = open(ctfproglog, "w")
		ctfprogproc = subprocess.Popen(self.ctfprgmexe, shell=True, stdin=subprocess.PIPE, stdout=logf)
		apDisplay.printColor(self.ctfprgmexe, "magenta")
		apDisplay.printColor(line1cmd.strip(),"magenta")
		apDisplay.printColor(line2cmd.strip(),"magenta")
		apDisplay.printColor(line3cmd.strip(),"magenta")
		apDisplay.printColor(line4cmd.strip(),"magenta")
		ctfprogproc.stdin.write(line1cmd)
		ctfprogproc.stdin.write(line2cmd)
		ctfprogproc.stdin.write(line3cmd)
		ctfprogproc.stdin.write(line4cmd)
		ctfprogproc.communicate()
		logf.close()

		apDisplay.printMsg("ctf estimation completed in "+apDisplay.timeString(time.time()-t0))

		#apFile.removeFile(inputparams['input'])

		### parse ctf estimation output
		self.ctfvalues = {}
		logf = open(ctfproglog, "r")

		## ctffind & ctftilt have diff # values
		numvals = 6
		if self.params['ctftilt'] is True:
			numvals=8 
		for line in logf:
			sline = line.strip()
			if sline[-12:] == "Final Values":
				#print sline
				if '**********' in sline:
					sline = re.sub('**********', ' **********', sline)
				bits = sline.split()
				if len(bits) != numvals:
					apDisplay.printError("wrong number of values in "+str(bits))
				for i,bit in enumerate(bits[0:(numvals-2)]):
					bits[i] = float(bit)
				self.ctfvalues = {
					'defocus1':	float(bits[0])*1e-10,
					'defocus2':	float(bits[1])*1e-10,
					# WARNING: this is the negative of the direct result
					'angle_astigmatism':	float(bits[2]),
					'amplitude_contrast': inputparams['ampcnst'],
					'cross_correlation':	float(bits[numvals-3]),
					'nominal':	nominal*1e-10,
					'defocusinit':	bestdef*1e-10,
					'cs': self.params['cs'],
					'volts': imgdata['scope']['high tension'],
					'confidence': float(bits[numvals-3]),
					'confidence_d': round(math.sqrt(abs(float(bits[numvals-3]))), 5)
				}
				if self.params['ctftilt'] is True:
					self.ctfvalues['tilt_axis_angle']=float(bits[3])
					self.ctfvalues['tilt_angle']=float(bits[4])

		### write to log file
		f = open("ctfvalues.log", "a")
		f.write("=== "+imgdata['filename']+" ===\n")
		if not self.ctfvalues:
			nominaldf =  imgdata['scope']['defocus']
		else:
			nominaldf = self.ctfvalues['nominal']
		line1 = ("nominal=%.1e, bestdef=%.1e," %
			( nominaldf, self.ctfvalues['defocusinit']))
		if self.params['ctftilt'] is True:
			self.ctfvalues['origtiltang'] = tiltang
			line1+=" tilt=%.1f,"%tiltang
		apDisplay.printMsg(line1)
		f.write(line1)
		line2 = ("def_1=%.1e, def_2=%.1e, astig_angle=%.1f, cross_corr=%.3f,\n" %
			( self.ctfvalues['defocus1'], self.ctfvalues['defocus2'], self.ctfvalues['angle_astigmatism'],
				self.ctfvalues['cross_correlation'] ))
		if self.params['ctftilt'] is True:
			line2+= ("tilt_angle=%.1f, tilt_axis_angle=%.1f,\n" %
				(self.ctfvalues['tilt_angle'], self.ctfvalues['tilt_axis_angle']))
		apDisplay.printMsg(line2)
		f.write(line2)
		f.close()

		#convert powerspectra to JPEG
		outputjpgbase = os.path.basename(os.path.splitext(inputparams['output'])[0]+".jpg")
		self.lastjpg = outputjpgbase
		outputjpg = os.path.join(self.powerspecdir, self.lastjpg)
		powspec = apImage.mrcToArray(inputparams['output'])
		apImage.arrayToJpeg(powspec, outputjpg)
		shutil.move(inputparams['output'], os.path.join(self.powerspecdir, inputparams['output']))
		self.ctfvalues['graph1'] = outputjpg

		#apFile.removeFile(inputparams['input'])

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.refineEllipseLoop(fftarray, lowerbound, upperbound)

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

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

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

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

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

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

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

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

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

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

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

        return
	def processImage(self, imgdata):
		self.ctfvalues = {}
		bestdef  = ctfdb.getBestCtfByResolution(imgdata, msg=True)
		apix = apDatabase.getPixelSize(imgdata)
		if (not (self.params['onepass'] and self.params['zeropass'])):
			maskhighpass = False
			ace2inputpath = os.path.join(imgdata['session']['image path'],imgdata['filename']+".mrc")
		else:
			maskhighpass = True
			filterimg = apImage.maskHighPassFilter(imgdata['image'],apix,1,self.params['zeropass'],self.params['onepass'])
			ace2inputpath = os.path.join(self.params['rundir'],imgdata['filename']+".mrc")
			mrc.write(filterimg,ace2inputpath)

		# make sure that the image is a square
		dimx = imgdata['camera']['dimension']['x']
		dimy = imgdata['camera']['dimension']['y']
		if dimx != dimy:
			dims = [dimx,dimy]
			dims.sort()
			apDisplay.printMsg("resizing image: %ix%i to %ix%i" % (dimx,dimy,dims[0],dims[0]))
			mrcarray = apImage.mrcToArray(ace2inputpath,msg=False)
			clippedmrc = apImage.frame_cut(mrcarray,[dims[0],dims[0]])
			ace2inputpath = os.path.join(self.params['rundir'],imgdata['filename']+".mrc")
			apImage.arrayToMrc(clippedmrc,ace2inputpath,msg=False)

		### pad out image to speed up FFT calculations for non-standard image sizes
		print "checking prime factor"
		if primefactor.isGoodStack(dimx) is False:
			goodsize = primefactor.getNextEvenPrime(dimx)
			factor = float(goodsize) / float(dimx)
			apDisplay.printMsg("padding image:  %ix%i to %ix%i" % (dimx,dimy,dimx*factor,dimy*factor))
			mrcarray = apImage.mrcToArray(ace2inputpath,msg=False)
#			paddedmrc = imagefun.pad(mrcarray, None, factor)
			paddedmrc = apImage.frame_constant(mrcarray, (dimx*factor,dimy*factor), cval=mrcarray.mean())
			ace2inputpath = os.path.join(self.params['rundir'],imgdata['filename']+".mrc")
			apImage.arrayToMrc(paddedmrc,ace2inputpath,msg=False)

		inputparams = {
			'input': ace2inputpath,
			'cs': self.params['cs'],
			'kv': imgdata['scope']['high tension']/1000.0,
			'apix': apix,
			'binby': self.params['bin'],
		}

		### make standard input for ACE 2
		apDisplay.printMsg("Ace2 executable: "+self.ace2exe)
		commandline = ( self.ace2exe
			+ " -i " + str(inputparams['input'])
			+ " -b " + str(inputparams['binby'])
			+ " -c " + str(inputparams['cs'])
			+ " -k " + str(inputparams['kv'])
			+ " -a " + str(inputparams['apix'])
			+ " -e " + str(self.params['edge_b'])+","+str(self.params['edge_t'])
			+ " -r " + str(self.params['rotblur'])
			+ "\n" )

		### run ace2
		apDisplay.printMsg("running ace2 at "+time.asctime())
		apDisplay.printColor(commandline, "purple")

		t0 = time.time()

		if self.params['verbose'] is True:
			ace2proc = subprocess.Popen(commandline, shell=True)
		else:
			aceoutf = open("ace2.out", "a")
			aceerrf = open("ace2.err", "a")
			ace2proc = subprocess.Popen(commandline, shell=True, stderr=aceerrf, stdout=aceoutf)

		ace2proc.wait()

		### check if ace2 worked
		basename = os.path.basename(ace2inputpath)
		imagelog = basename+".ctf.txt"
		if not os.path.isfile(imagelog) and self.stats['count'] <= 1:
			### ace2 always crashes on first image??? .fft_wisdom file??
			time.sleep(1)

			if self.params['verbose'] is True:
				ace2proc = subprocess.Popen(commandline, shell=True)
			else:
				aceoutf = open("ace2.out", "a")
				aceerrf = open("ace2.err", "a")
				ace2proc = subprocess.Popen(commandline, shell=True, stderr=aceerrf, stdout=aceoutf)

			ace2proc.wait()

		if self.params['verbose'] is False:
			aceoutf.close()
			aceerrf.close()
		if not os.path.isfile(imagelog):
			lddcmd = "ldd "+self.ace2exe
			lddproc = subprocess.Popen(lddcmd, shell=True)
			lddproc.wait()
			apDisplay.printError("ace2 did not run")
		apDisplay.printMsg("ace2 completed in " + apDisplay.timeString(time.time()-t0))

		### parse log file
		self.ctfvalues = {
			'cs': self.params['cs'],
			'volts': imgdata['scope']['high tension'],
		}
		logf = open(imagelog, "r")
		apDisplay.printMsg("reading log file %s"%(imagelog))
		for line in logf:
			sline = line.strip()
			if re.search("^Final Defocus: ", sline):
				### old ACE2
				apDisplay.printError("This old version of ACE2 has a bug in the astigmastism, please upgrade ACE2 now")
				#parts = sline.split()
				#self.ctfvalues['defocus1'] = float(parts[2])
				#self.ctfvalues['defocus2'] = float(parts[3])
				### convert to degrees
				#self.ctfvalues['angle_astigmatism'] = math.degrees(float(parts[4]))
			elif re.search("^Final Defocus \(m,m,deg\):", sline):
				### new ACE2
				apDisplay.printMsg("Reading new ACE2 defocus")
				parts = sline.split()
				#print parts
				self.ctfvalues['defocus1'] = float(parts[3])
				self.ctfvalues['defocus2'] = float(parts[4])
				# ace2 defines negative angle from +x toward +y
				self.ctfvalues['angle_astigmatism'] = -float(parts[5])
			elif re.search("^Amplitude Contrast:",sline):
				parts = sline.split()
				self.ctfvalues['amplitude_contrast'] = float(parts[2])
			elif re.search("^Confidence:",sline):
				parts = sline.split()
				self.ctfvalues['confidence'] = float(parts[1])
				self.ctfvalues['confidence_d'] = float(parts[1])
		logf.close()

		### summary stats
		apDisplay.printMsg("============")
		avgdf = (self.ctfvalues['defocus1']+self.ctfvalues['defocus2'])/2.0
		ampconst = 100.0*self.ctfvalues['amplitude_contrast']
		pererror = 100.0 * (self.ctfvalues['defocus1']-self.ctfvalues['defocus2']) / avgdf
		apDisplay.printMsg("Defocus: %.3f x %.3f um (%.2f percent astigmatism)"%
			(self.ctfvalues['defocus1']*1.0e6, self.ctfvalues['defocus2']*1.0e6, pererror ))
		apDisplay.printMsg("Angle astigmatism: %.2f degrees"%(self.ctfvalues['angle_astigmatism']))
		apDisplay.printMsg("Amplitude contrast: %.2f percent"%(ampconst))

		apDisplay.printColor("Final confidence: %.3f"%(self.ctfvalues['confidence']),'cyan')

		### double check that the values are reasonable
		if avgdf > self.params['maxdefocus'] or avgdf < self.params['mindefocus']:
			apDisplay.printWarning("bad defocus estimate, not committing values to database")
			self.badprocess = True

		if ampconst < 0.0 or ampconst > 80.0:
			apDisplay.printWarning("bad amplitude contrast, not committing values to database")
			self.badprocess = True

		if self.ctfvalues['confidence'] < 0.2:
			apDisplay.printWarning("bad confidence value, not committing values to database")
			self.badprocess = True

		## create power spectra jpeg
		mrcfile = imgdata['filename']+".mrc.edge.mrc"
		if os.path.isfile(mrcfile):
			jpegfile = os.path.join(self.powerspecdir, apDisplay.short(imgdata['filename'])+".jpg")
			ps = apImage.mrcToArray(mrcfile,msg=False)
			c = numpy.array(ps.shape)/2.0
			ps[c[0]-0,c[1]-0] = ps.mean()
			ps[c[0]-1,c[1]-0] = ps.mean()
			ps[c[0]-0,c[1]-1] = ps.mean()
			ps[c[0]-1,c[1]-1] = ps.mean()
			#print "%.3f -- %.3f -- %.3f"%(ps.min(), ps.mean(), ps.max())
			ps = numpy.log(ps+1.0)
			ps = (ps-ps.mean())/ps.std()
			cutoff = -2.0*ps.min()
			ps = numpy.where(ps > cutoff, cutoff, ps)
			cutoff = ps.mean()
			ps = numpy.where(ps < cutoff, cutoff, ps)
			#print "%.3f -- %.3f -- %.3f"%(ps.min(), ps.mean(), ps.max())
			apImage.arrayToJpeg(ps, jpegfile, msg=False)
			apFile.removeFile(mrcfile)
			self.ctfvalues['graph3'] = jpegfile
		otherfiles = glob.glob(imgdata['filename']+".*.txt")

		### remove extra debugging files
		for filename in otherfiles:
			if filename[-9:] == ".norm.txt":
				continue
			elif filename[-8:] == ".ctf.txt":
				continue
			else:
				apFile.removeFile(filename)

		if maskhighpass and os.path.isfile(ace2inputpath):
			apFile.removeFile(ace2inputpath)

		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
		count += 1
		imagename = os.path.basename(imgfile)
		imagename = imagename.replace(".mrc", "")
		imgdata = apDatabase.getImageData(imagename)

		### change project
		projid = apProject.getProjectIdFromImageData(imgdata)
		newdbname = apProject.getAppionDBFromProjectId(projid)
		sinedon.setConfig('appiondata', db=newdbname)

		powerspecfile = apDisplay.short(imagename)+"-powerspec.jpg"
		if os.path.isfile(powerspecfile):
			apDisplay.printColor("Skipping image %s, already complete"%(apDisplay.short(imagename)), "cyan")
			continue

		ctfdata = ctfdb.getBestCtfByResolution(imgdata)
		#ctfdata, bestconf = ctfdb.getBestCtfValueForImage(imgdata, method="ctffind")
		#ctfdata, bestconf = ctfdb.getBestCtfValueForImage(imgdata, method="ace2")
		if ctfdata is None:
			apDisplay.printColor("Skipping image %s, no CTF data"%(apDisplay.short(imagename)), "red")
			continue
		#print ctfdata
		if ctfdata['confidence_30_10'] < 0.88:
			apDisplay.printColor("Skipping image %s, poor confidence"%(apDisplay.short(imagename)), "red")
			continue
		"""
		if ctfdata['resolution_50_percent'] > 10 or ctfdata['resolution_50_percent'] < 7.5:
			apDisplay.printColor("Skipping image %s, not right 50per resolution"%(apDisplay.short(imagename)), "red")
			continue
		if ctfdata['resolution_80_percent'] > 13 or ctfdata['resolution_80_percent'] < 8.5:
			apDisplay.printColor("Skipping image %s, not right 80per resolution"%(apDisplay.short(imagename)), "red")
Example #13
0
    def processImage(self, imgdata):
        self.ctfvalues = {}
        bestdef = ctfdb.getBestCtfByResolution(imgdata, msg=True)
        apix = apDatabase.getPixelSize(imgdata)
        if (not (self.params['onepass'] and self.params['zeropass'])):
            maskhighpass = False
            ace2inputpath = os.path.join(imgdata['session']['image path'],
                                         imgdata['filename'] + ".mrc")
        else:
            maskhighpass = True
            filterimg = apImage.maskHighPassFilter(imgdata['image'], apix, 1,
                                                   self.params['zeropass'],
                                                   self.params['onepass'])
            ace2inputpath = os.path.join(self.params['rundir'],
                                         imgdata['filename'] + ".mrc")
            mrc.write(filterimg, ace2inputpath)

        # make sure that the image is a square
        dimx = imgdata['camera']['dimension']['x']
        dimy = imgdata['camera']['dimension']['y']
        if dimx != dimy:
            dims = [dimx, dimy]
            dims.sort()
            apDisplay.printMsg("resizing image: %ix%i to %ix%i" %
                               (dimx, dimy, dims[0], dims[0]))
            mrcarray = apImage.mrcToArray(ace2inputpath, msg=False)
            clippedmrc = apImage.frame_cut(mrcarray, [dims[0], dims[0]])
            ace2inputpath = os.path.join(self.params['rundir'],
                                         imgdata['filename'] + ".mrc")
            apImage.arrayToMrc(clippedmrc, ace2inputpath, msg=False)

        ### pad out image to speed up FFT calculations for non-standard image sizes
        print "checking prime factor"
        if primefactor.isGoodStack(dimx) is False:
            goodsize = primefactor.getNextEvenPrime(dimx)
            factor = float(goodsize) / float(dimx)
            apDisplay.printMsg("padding image:  %ix%i to %ix%i" %
                               (dimx, dimy, dimx * factor, dimy * factor))
            mrcarray = apImage.mrcToArray(ace2inputpath, msg=False)
            #			paddedmrc = imagefun.pad(mrcarray, None, factor)
            paddedmrc = apImage.frame_constant(mrcarray,
                                               (dimx * factor, dimy * factor),
                                               cval=mrcarray.mean())
            ace2inputpath = os.path.join(self.params['rundir'],
                                         imgdata['filename'] + ".mrc")
            apImage.arrayToMrc(paddedmrc, ace2inputpath, msg=False)

        inputparams = {
            'input': ace2inputpath,
            'cs': self.params['cs'],
            'kv': imgdata['scope']['high tension'] / 1000.0,
            'apix': apix,
            'binby': self.params['bin'],
        }

        ### make standard input for ACE 2
        apDisplay.printMsg("Ace2 executable: " + self.ace2exe)
        commandline = (self.ace2exe + " -i " + str(inputparams['input']) +
                       " -b " + str(inputparams['binby']) + " -c " +
                       str(inputparams['cs']) + " -k " +
                       str(inputparams['kv']) + " -a " +
                       str(inputparams['apix']) + " -e " +
                       str(self.params['edge_b']) + "," +
                       str(self.params['edge_t']) + " -r " +
                       str(self.params['rotblur']) + "\n")

        ### run ace2
        apDisplay.printMsg("running ace2 at " + time.asctime())
        apDisplay.printColor(commandline, "purple")

        t0 = time.time()

        if self.params['verbose'] is True:
            ace2proc = subprocess.Popen(commandline, shell=True)
        else:
            aceoutf = open("ace2.out", "a")
            aceerrf = open("ace2.err", "a")
            ace2proc = subprocess.Popen(commandline,
                                        shell=True,
                                        stderr=aceerrf,
                                        stdout=aceoutf)

        ace2proc.wait()

        ### check if ace2 worked
        basename = os.path.basename(ace2inputpath)
        imagelog = basename + ".ctf.txt"
        if not os.path.isfile(imagelog) and self.stats['count'] <= 1:
            ### ace2 always crashes on first image??? .fft_wisdom file??
            time.sleep(1)

            if self.params['verbose'] is True:
                ace2proc = subprocess.Popen(commandline, shell=True)
            else:
                aceoutf = open("ace2.out", "a")
                aceerrf = open("ace2.err", "a")
                ace2proc = subprocess.Popen(commandline,
                                            shell=True,
                                            stderr=aceerrf,
                                            stdout=aceoutf)

            ace2proc.wait()

        if self.params['verbose'] is False:
            aceoutf.close()
            aceerrf.close()
        if not os.path.isfile(imagelog):
            lddcmd = "ldd " + self.ace2exe
            lddproc = subprocess.Popen(lddcmd, shell=True)
            lddproc.wait()
            apDisplay.printError("ace2 did not run")
        apDisplay.printMsg("ace2 completed in " +
                           apDisplay.timeString(time.time() - t0))

        ### parse log file
        self.ctfvalues = {
            'cs': self.params['cs'],
            'volts': imgdata['scope']['high tension'],
        }
        logf = open(imagelog, "r")
        apDisplay.printMsg("reading log file %s" % (imagelog))
        for line in logf:
            sline = line.strip()
            if re.search("^Final Defocus: ", sline):
                ### old ACE2
                apDisplay.printError(
                    "This old version of ACE2 has a bug in the astigmastism, please upgrade ACE2 now"
                )
                #parts = sline.split()
                #self.ctfvalues['defocus1'] = float(parts[2])
                #self.ctfvalues['defocus2'] = float(parts[3])
                ### convert to degrees
                #self.ctfvalues['angle_astigmatism'] = math.degrees(float(parts[4]))
            elif re.search("^Final Defocus \(m,m,deg\):", sline):
                ### new ACE2
                apDisplay.printMsg("Reading new ACE2 defocus")
                parts = sline.split()
                #print parts
                self.ctfvalues['defocus1'] = float(parts[3])
                self.ctfvalues['defocus2'] = float(parts[4])
                # ace2 defines negative angle from +x toward +y
                self.ctfvalues['angle_astigmatism'] = -float(parts[5])
            elif re.search("^Amplitude Contrast:", sline):
                parts = sline.split()
                self.ctfvalues['amplitude_contrast'] = float(parts[2])
            elif re.search("^Confidence:", sline):
                parts = sline.split()
                self.ctfvalues['confidence'] = float(parts[1])
                self.ctfvalues['confidence_d'] = float(parts[1])
        logf.close()

        ### summary stats
        apDisplay.printMsg("============")
        avgdf = (self.ctfvalues['defocus1'] + self.ctfvalues['defocus2']) / 2.0
        ampconst = 100.0 * self.ctfvalues['amplitude_contrast']
        pererror = 100.0 * (self.ctfvalues['defocus1'] -
                            self.ctfvalues['defocus2']) / avgdf
        apDisplay.printMsg(
            "Defocus: %.3f x %.3f um (%.2f percent astigmatism)" %
            (self.ctfvalues['defocus1'] * 1.0e6,
             self.ctfvalues['defocus2'] * 1.0e6, pererror))
        apDisplay.printMsg("Angle astigmatism: %.2f degrees" %
                           (self.ctfvalues['angle_astigmatism']))
        apDisplay.printMsg("Amplitude contrast: %.2f percent" % (ampconst))

        apDisplay.printColor(
            "Final confidence: %.3f" % (self.ctfvalues['confidence']), 'cyan')

        ### double check that the values are reasonable
        if avgdf > self.params['maxdefocus'] or avgdf < self.params[
                'mindefocus']:
            apDisplay.printWarning(
                "bad defocus estimate, not committing values to database")
            self.badprocess = True

        if ampconst < 0.0 or ampconst > 80.0:
            apDisplay.printWarning(
                "bad amplitude contrast, not committing values to database")
            self.badprocess = True

        if self.ctfvalues['confidence'] < 0.2:
            apDisplay.printWarning(
                "bad confidence value, not committing values to database")
            self.badprocess = True

        ## create power spectra jpeg
        mrcfile = imgdata['filename'] + ".mrc.edge.mrc"
        if os.path.isfile(mrcfile):
            jpegfile = os.path.join(
                self.powerspecdir,
                apDisplay.short(imgdata['filename']) + ".jpg")
            ps = apImage.mrcToArray(mrcfile, msg=False)
            c = numpy.array(ps.shape) / 2.0
            ps[c[0] - 0, c[1] - 0] = ps.mean()
            ps[c[0] - 1, c[1] - 0] = ps.mean()
            ps[c[0] - 0, c[1] - 1] = ps.mean()
            ps[c[0] - 1, c[1] - 1] = ps.mean()
            #print "%.3f -- %.3f -- %.3f"%(ps.min(), ps.mean(), ps.max())
            ps = numpy.log(ps + 1.0)
            ps = (ps - ps.mean()) / ps.std()
            cutoff = -2.0 * ps.min()
            ps = numpy.where(ps > cutoff, cutoff, ps)
            cutoff = ps.mean()
            ps = numpy.where(ps < cutoff, cutoff, ps)
            #print "%.3f -- %.3f -- %.3f"%(ps.min(), ps.mean(), ps.max())
            apImage.arrayToJpeg(ps, jpegfile, msg=False)
            apFile.removeFile(mrcfile)
            self.ctfvalues['graph3'] = jpegfile
        otherfiles = glob.glob(imgdata['filename'] + ".*.txt")

        ### remove extra debugging files
        for filename in otherfiles:
            if filename[-9:] == ".norm.txt":
                continue
            elif filename[-8:] == ".ctf.txt":
                continue
            else:
                apFile.removeFile(filename)

        if maskhighpass and os.path.isfile(ace2inputpath):
            apFile.removeFile(ace2inputpath)

        return
	def processImage(self, imgdata):
		"""
		time ./ctffind3.exe << eof
		Input image file name                  [input.mrc] : 15aug13neil2_14jul14d_05sq_012hl_02ed-a.mrc
		Output diagnostic filename
		[diagnostic_output.mrc]                            : 15aug13neil2_14jul14d_05sq_012hl_02ed-a-pow.mrc
		Pixel size                                   [1.0] : 2.7
		Acceleration voltage                       [300.0] : 300 
		Spherical aberration                         [2.7] : 2.7
		Amplitude contrast                          [0.07] : 0.07
		Size of power spectrum to compute            [512] : 512
		Minimum resolution                          [30.0] : 20
		Maximum resolution                           [5.0] : 5
		Minimum defocus                           [5000.0] : 
		Maximum defocus                          [50000.0] : 
		Defocus search step                        [500.0] : 
		Expected (tolerated) astigmatism           [100.0] : 
		Find additional phase shift?                  [no] : 
		"""
		paramInputOrder = ['input', 'output', 'apix', 'kv', 'cs', 'ampcontrast', 'fieldsize',
			'resmin', 'resmax', 'defmin', 'defmax', 'defstep', 'expect_astig', 'phase', 'newline',]

		#get Defocus in Angstroms
		self.ctfvalues = {}
		nominal = abs(imgdata['scope']['defocus']*-1.0e10)
		ctfvalue = ctfdb.getBestCtfByResolution(imgdata)
		if ctfvalue is not None:
			"""
			## CTFFIND V3.5 (7-March-2012) prefers the smaller of the two values for astigmatic images
			I found that say you have an image with 1.1um and 1.5um defocus astigmatism. If you give 
			CTFFIND the average value of 1.3um for the defocus and 0.4um astig (dast) then it will 
			try to fit 1.3um and 1.8um, so you need to give it the minimum value (1.1um) for it to 
			fit 1.1um and 1.5um.
			"""
			bestdef = min(ctfvalue['defocus1'],ctfvalue['defocus2'])*1.0e10
		else:
			bestdef = nominal
		if ctfvalue is not None and self.params['bestdb'] is True:
			bestampcontrast = round(ctfvalue['amplitude_contrast'],3)
			beststigdiff = round(abs(ctfvalue['defocus1'] - ctfvalue['defocus2'])*1e10,1)
		else:
			bestampcontrast = self.params['ampcontrast']
			beststigdiff = self.params['dast']*10000.

		if ctfvalue is not None and self.params['bestdb'] is True:
			### set res max from resolution_80_percent
			gmean = (ctfvalue['resolution_80_percent']*ctfvalue['resolution_50_percent']*self.params['resmax'])**(1/3.)
			if gmean < self.params['resmin']*0.9:
				# replace only if valid Issue #3291
				self.params['resmax'] = round(gmean,2)
				apDisplay.printColor("Setting resmax to the geometric mean of resolution values", "purple")

		# dstep is the physical detector pixel size
		apix = apDatabase.getPixelSize(imgdata)
		# inputparams defocii and astig are in Angstroms
		inputparams = {
			'orig': os.path.join(imgdata['session']['image path'], imgdata['filename']+".mrc"),
			'input': apDisplay.short(imgdata['filename'])+".mrc",
			'output': apDisplay.short(imgdata['filename'])+"-pow.mrc",

			'apix': apix,
			'kv': imgdata['scope']['high tension']/1000.0,			
			'cs': self.params['cs'],
			'ampcontrast': bestampcontrast,
			'fieldsize': self.params['fieldsize'],
			'resmin': self.params['resmin'],
			'resmax': self.params['resmax'],
			
			'defstep': self.params['defstep']*10000., #round(defocus/32.0, 1),
			'expect_astig': beststigdiff,
			'phase': 'no', # this is a secondary amp contrast term for phase plates
			'newline': '\n',
		}
		defrange = self.params['defstep'] * self.params['numstep'] * 1e4 ## do 25 steps in either direction # in angstrum
		inputparams['defmin']= round(bestdef-defrange, 1) #in angstrom 
		if inputparams['defmin'] < 0:
			apDisplay.printWarning("Defocus minimum is less than zero")
			inputparams['defmin'] = inputparams['defstep']
		inputparams['defmax']= round(bestdef+defrange, 1) #in angstrom
		apDisplay.printColor("Defocus search range: %d A to %d A (%.2f to %.2f um)"
			%(inputparams['defmin'], inputparams['defmax'], 
			inputparams['defmin']*1e-4, inputparams['defmax']*1e-4), "cyan")

		### secondary lock check right before it starts on the real part
		if self.params['parallel'] and os.path.isfile(apDisplay.short(imgdata['filename'])+".mrc"):
			# This is a secondary image lock check, checking the first output of the process.
			# It alone is not good enough
			apDisplay.printWarning('Some other parallel process is working on the same image. Skipping')
			return
		### create local link to image
		if not os.path.exists(inputparams['input']):
			os.symlink(inputparams['orig'], inputparams['input'])

		if os.path.isfile(inputparams['output']):
			# program crashes if this file exists
			apFile.removeFile(inputparams['output'])

		t0 = time.time()
		apDisplay.printMsg("running ctf estimation at "+time.asctime())
		for paramName in paramInputOrder:
			apDisplay.printColor("%s = %s"%(paramName,inputparams[paramName]),"magenta")
		print ""
		ctfprogproc = subprocess.Popen(self.ctfprgmexe, shell=True, stdin=subprocess.PIPE,)		
		apDisplay.printColor(self.ctfprgmexe, "magenta")
		for paramName in paramInputOrder:
			apDisplay.printColor(inputparams[paramName],"magenta")
			ctfprogproc.stdin.write(str(inputparams[paramName])+'\n')
		ctfprogproc.communicate()
		tdiff = time.time()-t0
		apDisplay.printMsg("ctf estimation completed in "+apDisplay.timeString(tdiff))
		if tdiff < 1.0:
			apDisplay.printError("Failed to run CTFFIND4 program...")

		### cannot run ctffind_plot_results.sh on CentOS 6
		# This script requires gnuplot version >= 4.6, but you have version 4.2

		### parse ctf estimation output
		self.ctfvalues = {}
		ctfproglog = apDisplay.short(imgdata['filename'])+"-pow.txt"		
		apDisplay.printMsg("reading %s"%(ctfproglog))
		logf = open(ctfproglog, "r")

		for line in logf:
			sline = line.strip()
			if sline.startswith('#'):
				continue
			bits = sline.split()
			self.ctfvalues = {
				'imagenum': int(float(bits[0])),
				'defocus2':	float(bits[1])*1e-10,
				'defocus1':	float(bits[2])*1e-10,
				'angle_astigmatism':	float(bits[3]),
				'extra_phase':	float(bits[4]),
				'amplitude_contrast': inputparams['ampcontrast'],
				'cross_correlation':	float(bits[5]),
				'ctffind4_resolution':	float(bits[6]),
				'defocusinit':	bestdef*1e-10,
				'cs': self.params['cs'],
				'volts': imgdata['scope']['high tension'],
				'confidence': float(bits[5]),
				'confidence_d': round(math.sqrt(abs(float(bits[5]))), 5)
			}

		print self.ctfvalues

		#convert powerspectra to JPEG
		outputjpgbase = apDisplay.short(imgdata['filename'])+"-pow.jpg"
		self.lastjpg = outputjpgbase
		outputjpg = os.path.join(self.powerspecdir, self.lastjpg)
		powspec = apImage.mrcToArray(inputparams['output'])
		apImage.arrayToJpeg(powspec, outputjpg)
		shutil.move(inputparams['output'], os.path.join(self.powerspecdir, inputparams['output']))
		self.ctfvalues['graph1'] = outputjpg

		#apFile.removeFile(inputparams['input'])

		return
def runAce(matlab, imgdata, params, showprev=True):
	imgname = imgdata['filename']

	if showprev is True:
		bestctfvalue = ctfdb.getBestCtfByResolution(imgdata)
		if bestctfvalue:
			bestconf = ctfdb.calculateConfidenceScore(bestctfvalue)
			print ( "Prev best: '"+bestctfvalue['acerun']['name']+"', conf="+
				apDisplay.colorProb(bestconf)+", defocus="+str(round(-1.0*abs(bestctfvalue['defocus1']*1.0e6),2))+
				" microns" )

	if params['uncorrected']:
		tmpname='temporaryCorrectedImage.mrc'
		imgarray = apDBImage.correctImage(imgdata)
		imgpath = os.path.join(params['rundir'],tmpname)
		apImage.arrayToMrc(imgarray, imgpath)
		print "processing", imgpath
	else:
		imgpath = os.path.join(imgdata['session']['image path'], imgname+'.mrc')

	nominal = None
	if params['nominal'] is not None:
		nominal=params['nominal']
	elif params['newnominal'] is True:
		bestctfvalue = ctfdb.getBestCtfByResolution(imgdata)
		nominal = bestctfvalue['defocus1']
	if nominal is None:
		nominal = imgdata['scope']['defocus']

	if nominal is None or nominal > 0 or nominal < -15e-6:
			apDisplay.printWarning("Nominal should be of the form nominal=-1.2e-6"+\
				" for -1.2 microns NOT:"+str(nominal))

	#Neil's Hack
	#if 'autosample' in params and params['autosample']:
	#	x = abs(nominal*1.0e6)
	#	val = 1.585 + 0.057587 * x - 0.044106 * x**2 + 0.010877 * x**3
	#	resamplefr_override = round(val,3)
	#	print "resamplefr_override=",resamplefr_override
	#	pymat.eval(matlab, "resamplefr="+str(resamplefr_override)+";")

	pymat.eval(matlab,("dforig = %e;" % nominal))

	if params['stig'] == 0:
		plist = (imgpath, params['outtextfile'], params['display'], params['stig'],\
			params['medium'], -nominal, params['tempdir']+"/")
		acecmd = makeMatlabCmd("ctfparams = ace(",");",plist)
	else:
		plist = (imgname, imgpath, params['outtextfile'], params['opimagedir'], \
			params['matdir'], params['display'], params['stig'],\
			params['medium'], -nominal, params['tempdir']+"/", params['resamplefr'])
		acecmd = makeMatlabCmd("ctfparams = measureAstigmatism(",");",plist)

	#print acecmd
	pymat.eval(matlab,acecmd)

	matfile = os.path.join(params['matdir'], imgname+".mrc.mat")
	if params['stig']==0:
		savematcmd = "save('"+matfile+"','ctfparams','scopeparams', 'dforig');"
		pymat.eval(matlab,savematcmd)

	ctfvalue = pymat.get(matlab, 'ctfparams')
	ctfvalue=ctfvalue[0]

	printResults(params, nominal, ctfvalue)

	return ctfvalue