def alignParticlesToClasses(self, partStack, alignedClassStack, alignedPartStack):
		t1 = time.time()
		numPart = sparx.EMUtil.get_image_count(partStack)
		# for some reason this reports more classes than exist		
		numClasses = sparx.EMUtil.get_image_count(alignedClassStack)
		apDisplay.printMsg("aligning %d particles to %d classes"%(numPart, numClasses))		
		combinePartList = []
		self.particleAlignData = {}
		self.particleClass = {}
		totalPart = 0
		for newClassNum in range(numClasses):
			genId, genClassNum = self.newClassToGenClass[newClassNum]
			particleList = self.classMembersDict[genId][genClassNum]
			apDisplay.printMsg("aligning %d particles to class %d of %d (gen %d, num %d)"
				%(len(particleList), newClassNum, numClasses, genId, genClassNum))
			partEMDataList = sparx.EMData.read_images(partStack, particleList, not self.headerOnly)
			classEMData = sparx.get_im(alignedClassStack, newClassNum)
			totalPart += len(particleList)
			print newClassNum, particleList
			for i in range(len(particleList)):
				partEMData = partEMDataList[i]
				partId = particleList[i]
				self.particleClass[partId] = newClassNum
				alignData = sparx.align2d(partEMData, classEMData, 
					self.xrange, self.yrange, self.transStep, self.firstRing, 
					self.lastRing, self.ringStep, self.mode)
				self.particleAlignData[partId] = alignData
				combinePartList.append(partId)
		apDisplay.printColor("Finished aligning %d particles in %s"
			%(totalPart, apDisplay.timeString(time.time() - t1)), "cyan")
		
		t1 = time.time()
		### write out complete alignment parameters for all generations & aligned stack
		f = open("alignParticles.csv", "w")
		count = 0
		sys.stderr.write("writing %d aligned particles to file"%(len(combinePartList)))
		self.origPartToAlignPartDict = {}
		self.alignPartToOrigPartDict = {}
		for partId in combinePartList:
			self.origPartToAlignPartDict[partId] = count
			self.alignPartToOrigPartDict[count] = partId
			if count % 100 == 0:
				sys.stderr.write(".")
			# write alignments to file
			alignData = self.particleAlignData[partId]
			alpha, x, y, mirror, peak = alignData

			f.write("%.3f\t%.3f\t%.3f\t%d\t%d\n" % (alpha, x, y, mirror, peak))
			partEMData = sparx.EMData.read_images(partStack, [partId], not self.headerOnly)[0]
			alignPartEMData = sparx.rot_shift2D(partEMData, alpha, x, y, mirror)
			#we have to use count instead of partId, because not all images were aligned
			alignPartEMData.write_image(alignedPartStack, count)
			count += 1
		f.close()
		sys.stderr.write("\n")
		apDisplay.printColor("Finished creating aligned stack of %d particles in %s"
			%(count, apDisplay.timeString(time.time() - t1)), "cyan")	
		return
	def alignClassAverages(self, outputStack, numClassPerIter=None):
		t1 = time.time()
		outlist = "alignClassAverages.csv" 
		#output of the alignment program: new class number, original number, peak
		imageList, self.classToGenerationDict = self.readAndMergeStacks()

		if numClassPerIter is None:
			numClassPerIter = int(0.1*len(imageList))+1
	
		# randomly select an initial class
		init = int(random.random()*len(imageList))
		init = self.biggestClassNum
		apDisplay.printMsg( "initial align class %d of %d / num classes per iter %d"
			%(init, len(imageList)-1, numClassPerIter))
		temp = imageList[init].copy()
		temp.write_image(outputStack,0)
	
		#setup list of classes
		unusedClasses = range(0, len(imageList))
		unusedClasses.remove(init)

		#print unusedClasses
		f = open(outlist, "w")
		f.write("genId\tgenClass\tcombineClass\torigClass\talpha\tx\ty\tmirror\tpeak\n")
		newClassNumber = 1
		self.newClassAlignDataDict = {}
		self.newClassToGenClass = {}
		genId,origClass = self.classToGenerationDict[init]
		self.newClassToGenClass[0] = genId,origClass
		self.newClassAlignDataDict[0] = 0,0,0,0,1e6
		while(len(unusedClasses) > 0):
			t0 = time.time()
			peakList = []
			alignDict = {}
			indexList = []
			## go through classes and assign data
			apDisplay.printMsg("aligning %d remaining class averages"%(len(unusedClasses)))
			for classNum in unusedClasses:
				indexList.append(classNum)
				alignData = sparx.align2d(imageList[classNum], temp, self.xrange, self.yrange, 
					self.transStep, self.firstRing, self.lastRing, self.ringStep, self.mode) 
				alpha, x, y, mirror, peak = alignData
				peakList.append(peak)
				alignDict[classNum] = alignData
			
			peakArray = numpy.array(peakList)
			## fancy numpy thing to get the indices of top N values from an array
			peakSelect = peakArray.argsort()[-numClassPerIter:][::-1]
			#print peakSelect
			#print self.classToGenerationDict
			#print unusedClasses
			for index in peakSelect:
				classNum = indexList[index]
				alignData = alignDict[classNum]
				alpha, x, y, mirror, peak = alignData
				#print newClassNumber,classNum,peak
				genId,origClass = self.classToGenerationDict[classNum]
				self.newClassToGenClass[newClassNumber] = genId,origClass
				self.newClassAlignDataDict[newClassNumber] = alignData
				f.write("%d\t%d\t%d\t%d\t%.3f\t%.3f\t%.3f\t%d\t%.3f\n" 
					% (genId, origClass, newClassNumber, index, alpha, x, y, mirror, peak))
				temp = imageList[classNum].copy()
				temp = sparx.rot_shift2D(temp, alpha, x, y, mirror)
				temp.write_image(outputStack, newClassNumber)
				newClassNumber += 1
				unusedClasses.remove(classNum)
			apDisplay.printMsg("done in %s"%(apDisplay.timeString(time.time()-t0)))	
		f.close()
		apDisplay.printColor("Finished aligning classes in %s"
			%(apDisplay.timeString(time.time() - t1)), "cyan")	
		return