Thursday, July 10, 2014

I've Learned To Make Movies Of My Cellular Automata!

We met langton's ant some time ago, here is a movie I made of it.  Takes 7minutes.  Not sure how to speed up the movie yet.


here is my code:

#this is a generator function for yielding an NxN cellspace for langton's ant
#for gens number of generations
#grp2 and display are my own imaging library, it's a bit dopey, it doesn't take part in the
#creation of the movie file
 def langton(gens,N,px, delay, fill=lambda x,y : None ):
    """langton(gens,N,px,delay,fill) --
         do langton's ant in an NxN field
         withh pix size px and delay between steps
         fill is an optional function of cellspace and
         N which can fill cellspace with an initial
         pattern"""
    canv=grph2.Grph(N,N,px,'langton')
    #make a label box for gen 
    canv.gens=grph2.k.Label(canv.win)
    canv.gens.pack()
    dirs=((0,-1), (1,0), (0,1), (-1,0))
    gen,antx,anty,ant_dir=0,N//2, N//2, 0
    cellspace=[[0]*N for i in range(N)]
    fill(cellspace,N)
    display(cellspace, canv, N)
    canv.upd()
    for ii in xrange(gens):
        if cellspace[antx][anty]:
            cellspace[antx][anty]=0
            canv.unplot(antx,anty)
            ant_dir=(ant_dir-1)%4
        else:
            cellspace[antx][anty]=1
            canv.plot(antx,anty)
            ant_dir=(ant_dir+1)%4
      antx+=dirs[ant_dir][0]
      anty+=dirs[ant_dir][1]
      #put gen in label
      canv.gens.config(text=str(gen))
      canv.upd()
      gen+=1
      for i in xrange(delay): pass
      yield cellspace




#this creates a python imaging library image from a list of coordinates that
#should be painted as black squares of pxXpx number of pixels each

import Image

def ctimgf(coords,px,N,M,bkgr=(255,255,255),
                            pts=(0,0,0)):
  """ctigf(coords, fname, px, N, M, bkgr=(255,255,255),
                                    pts=(0,0,0) --
       return  an (N*px) X (M*px) image file for the coords"""
  im=Image.new('RGB',(N*px,M*px),bkgr)
  pix=im.load()
  for x,y in coords:
     for i in xrange(px):
        for j in xrange(px):
           pix[x*px+i,y*px+j]=pts
  return im


this calls my langtons ant program for gens number of generations and produces an image file for each generation

def langfmov(gens,sz,px,delay):
    """langfmov(gens,sz,px,delay,dur) -- display langton ant
         for gens gens and write a file for each gen in format
         lang00001.jpg etc.. """
   #create indesx i and cellspace cs for each generation of langton's ant
    for i, cs in enumerate(langton(gens,sz,px,delay)):
        #create a list of coordiates for each 'on' cell in the ant's pattern 
        lp=[(x,y) for x,yl in enumerate(cs)  #x is the row coordinate and yl is the row
                           for y,val in enumerate(yl) if val==1]  #y is the collumn coordinate
        #save an image file of those on and off coordinates
        ctimgf(lp,px,sz+1,sz+1).save("lang%05d.jpg" % i)



#my god that code is terse!  i let python get me carried away!  and i got x,y revered i think

#i call it:
langfmov(11000, 65, 4, 0)

#only took my computer a minute to produce 11,000 5kb jpgs

#the final command to make the movie i give in  linux:
avconv -f image2 -i lang%05d.jpg lang10000.avi

#('m not sure what the -f image2 command does!)
#only takes about 19seconds to create a 10mb movie!!!

No comments: