Esempio n. 1
0
def draw_ellipse_to_file(jpgfile, imgarray, major, minor, angle, center=None, 
		numpoints=64, color="#3d3df2", width=4):
	"""
	major - major axis radius (in pixels)
	minor - minor axis radius (in pixels)
	angle - angle (in degrees)
	center - position of centre of ellipse
	numpoints - # of points used that make an ellipse

	angle is positive toward y-axis
	"""
	if center is None:
		center = numpy.array(imgarray.shape, dtype=numpy.float)/2.0

	points = ellipse.generate_ellipse(major, minor, angle, center, numpoints, None, "step", True)
	x = points[:,0]
	y = points[:,1]

	## wrap around to end
	x = numpy.hstack((x, [x[0],]))
	y = numpy.hstack((y, [y[0],]))
	## convert image
	originalimage = imagefile.arrayToImage(imgarray)
	originalimage = originalimage.convert("RGB")
	pilimage = originalimage.copy()
	draw = ImageDraw.Draw(pilimage)
	for i in range(len(x)-1):
		xy = (x[i], y[i], x[i+1], y[i+1])
		draw.line(xy, fill=color, width=width)

	## create an alpha blend effect
	originalimage = Image.blend(originalimage, pilimage, 0.9)
	originalimage.save(jpgfile, "JPEG", quality=85)
	return
Esempio n. 2
0
def draw_ellipse_to_file(jpgfile, imgarray, major, minor, angle, center=None, 
                numpoints=64, color="#3d3df2", width=4):
        """
        major - major axis radius (in pixels)
        minor - minor axis radius (in pixels)
        angle - angle (in degrees)
        center - position of centre of ellipse
        numpoints - # of points used that make an ellipse

        angle is positive toward y-axis
        """
        if center is None:
                center = numpy.array(imgarray.shape, dtype=numpy.float)/2.0

        points = ellipse.generate_ellipse(major, minor, angle, center, numpoints, None, "step", True)
        x = points[:,0]
        y = points[:,1]

        ## wrap around to end
        x = numpy.hstack((x, [x[0],]))
        y = numpy.hstack((y, [y[0],]))
        ## convert image
        originalimage = imagefile.arrayToImage(imgarray)
        originalimage = originalimage.convert("RGB")
        pilimage = originalimage.copy()
        draw = ImageDraw.Draw(pilimage)
        for i in range(len(x)-1):
                xy = (x[i], y[i], x[i+1], y[i+1])
                draw.line(xy, fill=color, width=width)

        ## create an alpha blend effect
        originalimage = Image.blend(originalimage, pilimage, 0.9)
        originalimage.save(jpgfile, "JPEG", quality=85)
        return
	def drawPowerSpecImage(self, origpowerspec, maxsize=1200):

		origpowerspec = ctftools.trimPowerSpectraToOuterResolution(origpowerspec, self.plotlimit2DAngstrom, self.trimfreq)

		if self.debug is True:
			print "origpowerspec shape", origpowerspec.shape

		#compute elliptical average and merge with original image
		pixelrdata, rotdata = ctftools.ellipticalAverage(origpowerspec, self.ellipratio, self.angle,
			self.ringwidth*3, 1, full=True)
		ellipavgpowerspec = ctftools.unEllipticalAverage(pixelrdata, rotdata, 
			self.ellipratio, self.angle, origpowerspec.shape)
		halfshape = origpowerspec.shape[1]/2
		halfpowerspec = numpy.hstack( (origpowerspec[:,:halfshape] , ellipavgpowerspec[:,halfshape:] ) )
		if halfpowerspec.shape != origpowerspec.shape:
			apDisplay.printError("Error in power spectra creation")

		if max(halfpowerspec.shape) > maxsize:
			scale = maxsize/float(max(halfpowerspec.shape))
			#scale = math.sqrt((random.random()+random.random()+random.random())/3.0)
			apDisplay.printMsg( "Scaling final powerspec image by %.3f"%(scale))
			powerspec = imagefilter.scaleImage(halfpowerspec, scale)
		else:
			scale = 1280./float(max(halfpowerspec.shape))
			powerspec = imagefilter.scaleImage(halfpowerspec, scale)
			#scale = 1.0
			#powerspec = halfpowerspec.copy()

		self.scaleapix = self.trimapix
		self.scalefreq = self.trimfreq/scale
		if self.debug is True:
			print "orig pixel", self.apix
			print "trim pixel", self.trimapix
			print "scale pixel", self.scaleapix

		numzeros = 13

		radii1 = ctftools.getCtfExtrema(self.defocus1, self.scalefreq*1e10, 
			self.cs, self.volts, self.ampcontrast, numzeros=numzeros, zerotype="valley")
		radii2 = ctftools.getCtfExtrema(self.defocus2, self.scalefreq*1e10, 
			self.cs, self.volts, self.ampcontrast, numzeros=numzeros, zerotype="valley")

		#smallest of two defocii
		firstpeak = radii2[0]

		### 
		### PART 9: DRAW THE 2D POWERSPEC IMAGE
		### 
		center = numpy.array(powerspec.shape, dtype=numpy.float)/2.0
		foundzeros = min(len(radii1), len(radii2))
		"""
		pyplot.clf()
		ax = pyplot.subplot(1,1,1)
		pyplot.xticks([], [])
		pyplot.yticks([], [])
		pyplot.imshow(powerspec)
		pyplot.gray()
		for i in range(foundzeros):
			# because |def1| < |def2| ==> firstzero1 > firstzero2
			major = radii1[i]*2
			minor = radii2[i]*2
			ell = Ellipse(xy=center, width=major, height=minor, angle=self.angle+90, 
				fill=False, edgecolor="yellow", antialiased=True, linewidth=0.5)
			ax.add_artist(ell)
		pyplot.subplots_adjust(wspace=0, hspace=0, bottom=0, left=0, top=1, right=1, )
		self.newpowerspecfile = apDisplay.short(self.imgname)+"-powerspec-new.png"
		pyplot.savefig(self.newpowerspecfile, format="png", dpi=150, pad_inches=0.0)
		"""

		### 
		### PART 9: DRAW THE 2D POWERSPEC IMAGE
		### 
		apDisplay.printColor("PART 9: DRAW THE 2D POWERSPEC IMAGE", "magenta")

		center = numpy.array(powerspec.shape, dtype=numpy.float)/2.0
		originalimage = imagefile.arrayToImage(powerspec)
		originalimage = originalimage.convert("RGB")
		pilimage = originalimage.copy()
		draw = ImageDraw.Draw(pilimage)

		#########
		## draw astig axis line, if astig > 5%
		#########
		perdiff = 2*abs(self.defocus1-self.defocus2)/abs(self.defocus1+self.defocus2)
		if self.debug is True:
			print "Percent Difference %.1f"%(perdiff*100)
		if perdiff > 0.05:
			#print self.angle, radii2[0], center
			x = 1*firstpeak*math.cos(math.radians(self.angle))
			y = firstpeak*math.sin(math.radians(self.angle))
			#print x,y
			xy = (x+center[0], y+center[1], -x+center[0], -y+center[1])
			#print xy
			draw.line(xy, fill="#f23d3d", width=10)
		elif perdiff > 1e-6:
			#print self.angle, radii2[0], center
			x = 1*firstpeak*math.cos(math.radians(self.angle))
			y = firstpeak*math.sin(math.radians(self.angle))
			#print x,y
			xy = (x+center[0], y+center[1], -x+center[0], -y+center[1])
			#print xy
			draw.line(xy, fill="#f23d3d", width=2)

		#########
		## draw colored CTF Thon rings
		#########
		foundzeros = min(len(radii1), len(radii2))
		#color="#3d3dd2" #blue
		color="#ffd700" #gold
		for i in range(foundzeros):

			# because |def1| < |def2| ==> firstzero1 > firstzero2
			major = radii1[i]
			minor = radii2[i]
			if self.debug is True: 
				print "major=%.1f, minor=%.1f, angle=%.1f"%(major, minor, self.angle)
			if minor > powerspec.shape[0]/math.sqrt(3):
				# this limits how far we draw out the ellipses sqrt(3) to corner, just 2 inside line
				break
			width = int(math.ceil(math.sqrt(numzeros - i)))*2

			### determine color of circle
			currentres = 1.0/(major*self.scalefreq)
			if currentres > self.res80:
				ringcolor = "green"
			elif currentres > self.res50:
				ringcolor = "gold"
			else:
				ringcolor = "red"

			### determine number of points to use to draw ellipse, minimize distance btw points
			#isoceles triangle, b: radius ot CTF ring, a: distance btw points
			#a = 2 * b sin (theta/2)
			#a / 2b = sin(theta/2)
			#theta = 2 * asin (a/2b)
			#numpoints = 2 pi / theta
			## define a to be 5 pixels
			a = 40
			theta = 2.0 * math.asin (a/(2.0*major))
			skipfactor = 2
			numpoints = int(math.ceil(2.0*math.pi/theta/skipfactor))*skipfactor + 1
			#print "numpoints", numpoints


			points = ellipse.generate_ellipse(major, minor, 
				math.radians(self.angle), center, numpoints, None, "step", True)
			x = points[:,0]
			y = points[:,1]

			## wrap around to end
			x = numpy.hstack((x, [x[0],]))
			y = numpy.hstack((y, [y[0],]))
			## convert image

			numsteps = int(math.floor((len(x)-2)/skipfactor))
			for j in range(numsteps):
				k = j*skipfactor
				xy = (x[k], y[k], x[k+1], y[k+1])
				draw.line(xy, fill=ringcolor, width=width)

		#########
		## draw blue resolution ring
		#########
		# 1/res = freq * pixrad => pixrad = 1/(res*freq)
		maxrad = (max(powerspec.shape)-1)/2.0 - 3
		maxres = 1.0/(self.scalefreq*maxrad)
		bestres = math.ceil(maxres)
		pixrad = 1.0/(self.scalefreq*bestres)
		if self.debug is True:
			print "bestres %d Angstroms (max: %.3f)"%(bestres, maxres)
			print "pixrad %d (max: %.3f)"%(pixrad, maxrad)
		if pixrad > maxrad:
			apDisplay.printError("Too big of outer radius to draw")
		outpixrad = math.ceil(pixrad)+1
		inpixrad = math.floor(pixrad)-1
		for i in numpy.arange(-4.0,4.01,0.01):
			r = pixrad + i
			blackxy = numpy.array((center[0]-r,center[1]-r, 
				center[0]+r,center[1]+r), dtype=numpy.float64)
			draw.ellipse(tuple(blackxy), outline="black")
		for i in numpy.arange(-1.50,1.51,0.01):
			r = pixrad + i
			whitexy = numpy.array((center[0]-r,center[1]-r, 
				center[0]+r,center[1]+r), dtype=numpy.float64)
			draw.ellipse(tuple(whitexy), outline="#0BB5FF")

		#########
		## setup font to add text
		#########
		fontpath = "/usr/share/fonts/liberation/LiberationSans-Regular.ttf"
		from PIL import ImageFont
		if os.path.isfile(fontpath):
			fontsize = int(math.ceil( 48/2. * min(powerspec.shape)/float(maxsize))*2)
			font = ImageFont.truetype(fontpath, fontsize)
		else:
			font = ImageFont.load_default()

		#########
		## add resolution ring text
		#########
		angrad = maxrad/math.sqrt(2) + 1
		coord = (angrad+maxrad, angrad+maxrad)
		for i in [-2,2]:
			for j in [-2,2]:
				draw.text((coord[0]+i,coord[1]+j), "%.1f A"%(bestres), font=font, fill="black")
		draw.text(coord, "%.1f A"%(bestres), font=font, fill="#0BB5FF")

		#########
		## add defocus value text
		#########
		meandef = abs(self.defocus1+self.defocus2)/2.0
		deftext = "%.2f um"%(meandef*1e6)
		tsize = draw.textsize(deftext, font=font)
		coord = (powerspec.shape[0]-4-tsize[0], powerspec.shape[0]-4-tsize[1])
		for i in [-2,2]:
			for j in [-2,2]:
				draw.text((coord[0]+i,coord[1]+j), deftext, font=font, fill="black")
		draw.text(coord, deftext, font=font, fill="#AB82FF")

		#########
		## add text about what sides of powerspec are:
		## left - raw data; right - elliptical average data
		#########
		leftcoord = (4, 4)
		for i in [-3, -1, 0, 1, 3]:
			for j in [-3, -1, 0, 1, 3]:
				draw.text((leftcoord[0]+i,leftcoord[1]+j) , "Raw CTF Data", font=font, fill="black")
		draw.text(leftcoord, "Raw CTF Data", font=font, fill="#00BFFF")

		tsize = draw.textsize("Elliptical Average", font=font)
		xdist = powerspec.shape[0] - 4 - tsize[0]
		rightcoord = (xdist, 4)
		for i in [-2,2]:
			for j in [-2,2]:
				draw.text((rightcoord[0]+i,rightcoord[1]+j), "Elliptical Average", font=font, fill="black")
		draw.text(rightcoord, "Elliptical Average", font=font, fill="#00BFFF")

		#########
		## create an alpha blend effect
		#########
		originalimage = Image.blend(originalimage, pilimage, 0.95)
		apDisplay.printMsg("Saving 2D powerspectra to file: %s"%(self.powerspecfile))
		#pilimage.save(self.powerspecfile, "JPEG", quality=85)
		originalimage.save(self.powerspecfile, "JPEG", quality=85)
		if not os.path.isfile(self.powerspecfile):
			apDisplay.printWarning("power spec file not created")
		if self.debug is True:
			#powerspecjpg = Image.open(self.powerspecfile)
			#powerspecjpg.show()
			pass
		return