# Genetic Cellular Automaton execution
# Alice Durand and David Olsen, Physics 198/250 Spring 2007

from Tkinter import *
from GCAclass import *
from numpy import array

try:
	import pygame
	import pygame.surfarray as surfarray
except ImportError:
	raise ImportError, "Numeric and PyGame required."

def SpDisplayState(state,nSites,surface,CellSize): #displays state
	ConfigRect = pygame.Rect(0,0,nSites*CellSize,nSites*CellSize)
	surface.fill((0,0,0),ConfigRect)
	for i in range(nSites):
		for j in range(nSites):
				surface.fill(State.state[i][j],[i*CellSize,j*CellSize,CellSize,CellSize])

def step(): #function that advances the state and updates the window
	if int(tPop.get()) != gca.size or int(tSeed.get()) != gca.Seed:
		gca.__init__(int(tPop.get()), genemap, int(tSeed.get()))
		State.__init__(N,N)
		State.addelement(gca.ConvertToTuples())
	
	for nm in range(int(tStepCnt.get())):
		gca.iterate()
		if(float(tMut.get())!=0):gca.mutate(float(tMut.get()))
		State.addelement(gca.ConvertToTuples())
		SpDisplayState(State, N, screen, CellSize)
		pygame.display.flip()
		for event in pygame.event.get():
			if event.type == pygame.QUIT: sys.exit()
	
CellSize = 6 #various initialization parameters
N = 100
size = (N*CellSize, N*CellSize)
root = Tk()

#genemaps are dictionaries that hold a gene letter along with hex color values in arrays
#genemap = {'r':array([256,0,0]),'g':array([0,256,0]),'b':array([0,0,256])}
genemap = {'r':array([256,0,0]),'g':array([0,256,0]),'b':array([0,0,256]),'y':array([128,128,0]),'c':array([0,128,128]),'m':array([128,0,128])}
#genemap = {'r':array([256,0,0]),'g':array([0,256,0]),'b':array([0,0,256]),'y':array([256,256,0]),'c':array([0,256,256]),'m':array([256,0,256])}

#initialize population,matrix
gca = GCA1D(N,genemap,0)
State = StateMatrix(N,N)
State.addelement(gca.ConvertToTuples())


pygame.init()
screen = pygame.display.set_mode(size)

screen.fill((0,0,0))
pygame.display.flip()
sptmdiag = surfarray.pixels3d(screen)

bStep = Button(root,text='Step', command=step)
bStep.pack(side="right", padx=10)

fStepCnt = Frame(root, border=1)	#Frame
tStepCnt = Entry(fStepCnt, relief="sunken", text="50")	#Text entry
lStepCnt = Label(fStepCnt, text="Steps: ")	#Label
fStepCnt.pack(side="left", padx=10, pady=5)
tStepCnt.pack()
lStepCnt.pack(side="left", padx=5)

fPop = Frame(root, border=1)	#Frame
tPop = Entry(fPop, relief="sunken")	#Text entry
lPop = Label(fPop, text="Population: ")	#Label
fPop.pack(side="left", padx=10, pady=5)
tPop.pack()
lPop.pack(side="left", padx=5)

fSeed = Frame(root, border=1)	#Frame
tSeed = Entry(fSeed, relief="sunken")	#Text entry
lSeed = Label(fSeed, text="Seed: ")	#Label
fSeed.pack(side="left", padx=10, pady=5)
tSeed.pack()
lSeed.pack(side="left", padx=5)

fMut = Frame(root, border=1)
tMut = Entry(fMut, relief='sunken')
lMut = Label(fMut, text='Mutation Coefficient:')
fMut.pack(side="left", padx=10, pady=5)
tMut.pack()
lMut.pack(side="left", padx=5)

root.mainloop()
#Class file for Automaton

from random import randint,seed,random
from numpy import array

class GCA1D:
	def __init__(self,size,genemap,inseed):
		self.size = size
		self.Seed = inseed
		if inseed != 0:
			seed(inseed)
		self.genemap = genemap
		self.current = []
		self.next = []
		for i in range(size): #initializes the current state and sets up next state
			r1 = randint(0,len(genemap)-1)
			r2 = randint(0,len(genemap)-1)
			g1 = genemap.keys()[r1]
			g2 = genemap.keys()[r2]
			self.current.append([g1,g2])
			self.next.append([0,0])
			
	def iterate(self): #iteration algorithm, randomly selects 1 gene from each parent and gives to daughter cell
		for i in range(self.size):
			r1 = randint(0,1)
			r2 = randint(0,1)
			if ((i+1)== self.size):
				self.next[i] = [(self.current[i-1][r1]),(self.current[0][r2])]
			else:
				self.next[i] = [(self.current[i-1][r1]),(self.current[i+1][r2])]
                for i in range(self.size):
                        self.current[i] = self.next[i]
            		
	def mutate(self, mutcof): #allows for mutations
		for i in range(self.size):
			if random()<mutcof:
				r1,r2 = randint(0,len(self.genemap)-1),randint(0,len(self.genemap)-1)
				g1,g2 = self.genemap.keys()[r1],self.genemap.keys()[r2]
				self.current[i] = [g1,g2]
			
	
	def ConvertToTuples(self): #changes from the gene pair format to a color representation of the blending, in the form of a hex tuple.
		outseq = []
		for i in range(len(self.current)):
			color1 = self.genemap[self.current[i][0]]
			color2 = self.genemap[self.current[i][1]]
			color = (color1 + color2)/2
			for j in range(len(color)):
				if color[j]!=0:
					color[j]-=1
			color = tuple(color)
			outseq.append(color)
		return outseq

class StateMatrix: #a construct to hold the screen color variables to pass into pygame
	def __init__(self, Hsize, Vsize):
		self.state = []
		self.width = Hsize
		for i in range(Vsize):
			self.state.append([])
			for j in range(Hsize):
				self.state[i].append((0,0,0))
		
	def addelement(self,inseq): #function to add rows to the matrix, pops off 1st element and adds new state at the end
		self.state.append([])
		self.state.pop(0)
		for i in range((self.width-len(inseq))/2):
			self.state[-1].append((0,0,0))
		for element in inseq:
				self.state[-1].append(element)
		for i in range(self.width-len(self.state[-1])):
			self.state[-1].append((0,0,0))
#Cellular Automaton execution

from Tkinter import *
from GCAclass2 import *
from numpy import array

try:
	import pygame
	import pygame.surfarray as surfarray
except ImportError:
	raise ImportError, "Numeric and PyGame required."

def SpDisplayState(state,nSites,surface,CellSize): #displays state
	ConfigRect = pygame.Rect(0,0,nSites*CellSize,nSites*CellSize)
	surface.fill((0,0,0),ConfigRect)
	for i in range(nSites):
		for j in range(nSites):
				surface.fill(State.state[i][j],[i*CellSize,j*CellSize,CellSize,CellSize])

def step(): #function that advances the state and updates the window
	if int(tPop.get()) != gca.size or int(tSeed.get()) != gca.Seed:
		gca.__init__(int(tPop.get()), genemap, int(tSeed.get()))
		State.__init__(N,N)
		State.addelement(gca.ConvertToTuples())
	
	for nm in range(int(tStepCnt.get())):
		gca.iterate()
		if(float(tMut.get())!=0):gca.mutate(float(tMut.get()))
		State.addelement(gca.ConvertToTuples())
		SpDisplayState(State, N, screen, CellSize)
		pygame.display.flip()
		for event in pygame.event.get():
			if event.type == pygame.QUIT: sys.exit()
	
CellSize = 6 #various initialization parameters
N = 100
size = (N*CellSize, N*CellSize)
root = Tk()

#genemaps are dictionaries that hold a gene letter along with hex color values in arrays
genemap = {'r':array([256,0,0]),'g':array([0,256,0]),'b':array([0,0,256])}
#genemap = {'r':array([256,0,0]),'g':array([0,256,0]),'b':array([0,0,256]),'y':array([128,128,0]),'c':array([0,128,128]),'m':array([128,0,128])}
#genemap = {'r':array([256,0,0]),'g':array([0,256,0]),'b':array([0,0,256]),'y':array([256,256,0]),'c':array([0,256,256]),'m':array([256,0,256])}

#initialize population,matrix
gca = GCA1D(N,genemap,0)
State = StateMatrix(N,N)
State.addelement(gca.ConvertToTuples())


pygame.init()
screen = pygame.display.set_mode(size)

screen.fill((0,0,0))
pygame.display.flip()
sptmdiag = surfarray.pixels3d(screen)

bStep = Button(root,text='Step', command=step)
bStep.pack(side="right", padx=10)

fStepCnt = Frame(root, border=1)	#Frame
tStepCnt = Entry(fStepCnt, relief="sunken", text="50")	#Text entry
lStepCnt = Label(fStepCnt, text="Steps: ")	#Label
fStepCnt.pack(side="left", padx=10, pady=5)
tStepCnt.pack()
lStepCnt.pack(side="left", padx=5)

fPop = Frame(root, border=1)	#Frame
tPop = Entry(fPop, relief="sunken")	#Text entry
lPop = Label(fPop, text="Population: ")	#Label
fPop.pack(side="left", padx=10, pady=5)
tPop.pack()
lPop.pack(side="left", padx=5)

fSeed = Frame(root, border=1)	#Frame
tSeed = Entry(fSeed, relief="sunken")	#Text entry
lSeed = Label(fSeed, text="Seed: ")	#Label
fSeed.pack(side="left", padx=10, pady=5)
tSeed.pack()
lSeed.pack(side="left", padx=5)

fMut = Frame(root, border=1)
tMut = Entry(fMut, relief='sunken')
lMut = Label(fMut, text='Mutation Coefficient:')
fMut.pack(side="left", padx=10, pady=5)
tMut.pack()
lMut.pack(side="left", padx=5)

root.mainloop()
