Advertisement
Guest User

Neural Network Simulator for Blender2.5

a guest
Jul 9th, 2010
476
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 26.81 KB | None | 0 0
  1. #!/usr/bin/python
  2. ## RPython Neural Network - 0.2
  3. ## by Brett Hartshorn goatman.py@gmail.com
  4. ## License GNU GPL
  5. ## demo1 Python vs PyPy: http://www.youtube.com/watch?v=HwbDG3Rdi_Q
  6. ## demo2 Blender Rendering: http://www.youtube.com/watch?v=4sMrG2g7LmA
  7.  
  8. ## user defined options ##
  9. BLENDER_DIR = '../Desktop/blender25/blender'
  10. ## number of neurons, be careful with large numbers!
  11. COLUMNS = 24
  12. LAYERS = 3
  13. STEM = 4
  14.  
  15. '''
  16. Getting Started:
  17.  
  18.     Tested with Ubuntu Lucid and PyPy 1.3
  19.     (in theory works on Windows, but installing the PyPy toolchain and SDL headers would be a serious pain)
  20.     Why PyPy?  Because Python is too slow to run a simulation with any modest number of neurons.
  21.  
  22.     1. Download PyPy source code - see http://pypy.org
  23.  
  24.     2. Install GCC and SDL headers if you haven't already
  25.         apt-get install build-essential libsdl-dev
  26.  
  27.     3. Make this file executable: "chmod +x rAI.py"
  28.  
  29.     4. Modify the line above BLENDER_DIR to point to your blender25 installation
  30.  
  31.     5. Copy this file to your pypy root directory and run "./rAI.py"
  32.         (you can test just pypy compilation with "./rAI.py --pypy --subprocess")
  33.  
  34. How It Works:
  35.     This program is actually three programs in a single Python script,
  36.     some trickery with command line arguments is used to divide the programs.
  37.     When you run "./rAI.py" the top level begins, opening a GTK window,
  38.     When the drawing-area in the GTK window is realized it calls itself using the
  39.     subprocess module and passing "--pypy --subprocess" on the command line,
  40.     when the script is run this way it imports pypy and translates the simulator
  41.     into C, the SDL_WINDOWID environment variable is used to tell the PyPy
  42.     subprocess to draw into that xwindow ID.
  43.     After the simulation has run, you can dump it to Blender25 by clicking "view model"
  44.     When you do this blender is called with the -P argument pointing to itself (this script)
  45.     The script knows its being run from blender and creates the BlenderExport class
  46.     that handles converting the data.
  47.  
  48. Unfinished Work:
  49.  
  50.     For Blender visualization it would be nice to see which dendrites are polarized.
  51.  
  52.     Realtime Brain Input/Output: a brain sim without any input or output is pretty boring,
  53.         to input spikes into the network provide a function that writes a command to the pipe,
  54.         ( see "spike-all" and "spike-one" )
  55.         for example you could modify this program to open a socket, and then from the
  56.         Blender Game Engine your actuator sends a signal to the socket when something it touched,
  57.         depending on whats touched, the toplevel app will write a command to the pipe that
  58.         the PyPy subprocess is reading.
  59.         Getting output from the network is done the same way, pipe/socket -> client - do something.
  60.         ( note that single neuron spiking gives little information - its better you FFT the spikes into a
  61.         useable pattern that can drive some action )
  62.  
  63.     Skeleton code for learning/training the network, needs alot of work.
  64.  
  65.  
  66.  
  67. -----------------------------------------------------------
  68. PyPy Tips for Coders:
  69.  
  70. math.radians    not available
  71. random.uniform  not available
  72.  
  73. incorrect:
  74.     string.strip()  will not work without an arg
  75.     list.sort()     not available
  76.  
  77. correct:
  78.     string.strip(' ').strip('\n').strip('\t')       #strips all white space
  79.     list = sortd( list )                        # but the JIT prefers TimSort
  80.     list.pop( index )                       # no list.pop() with end as default
  81.  
  82. '''
  83.  
  84.  
  85. import os, sys, time, pickle
  86. import math             # math.radians is missing in pypy?
  87.  
  88. degToRad = math.pi / 180.0
  89. def radians(x):
  90.     """radians(x) -> converts angle x from degrees to radians
  91.     """
  92.     return x * degToRad
  93.  
  94. if '--blender' not in sys.argv:
  95.     from pypy.rlib import streamio
  96.     from pypy.rlib import rpoll
  97.     # apt-get install libsdl-dev
  98.     from pypy.rlib.rsdl import RSDL, RSDL_helper
  99.     from pypy.rlib.rarithmetic import r_uint
  100.     from pypy.rpython.lltypesystem import lltype, rffi
  101.     from pypy.rlib.listsort import TimSort
  102.     from pypy.rlib.jit import hint, we_are_jitted, JitDriver, purefunction_promote
  103.  
  104. #random.randrange(0, up)        # not a replacement for random.uniform
  105. #Choose a random item from range(start, stop[, step]).  
  106. #This fixes the problem with randint() which includes the
  107. #endpoint; in Python this is usually not what you want.
  108.  
  109.  
  110. if '--pypy' in sys.argv:        # random.random works in pypy, but random.uniform is missing?
  111.     from pypy.rlib import rrandom
  112.     RAND = rrandom.Random()
  113.     RAND.init_by_array([1, 2, 3, 4])
  114.     def random(): return RAND.random()
  115.     def uniform(start,end): return ( RAND.random() * (end-start) ) - start
  116. else:
  117.     from random import *
  118.  
  119. def distance( v1, v2 ):
  120.     dx = v1[0] - v2[0]
  121.     dy = v1[1] - v2[1]
  122.     dz = v1[2] - v2[2]
  123.     t = dx*dx + dy*dy + dz*dz
  124.     return math.sqrt( float(t) )
  125.  
  126. if '--blender' not in sys.argv:
  127.     Njitdriver = JitDriver(
  128.         greens = 'cur train times branes last_spike spikers temporal thresh triggers self abs_refactory abs_refactory_value'.split(),
  129.         reds = 'i t a b c bias neuron'.split()
  130.     )
  131. class RecurrentSpikingModel(object):
  132.     '''
  133.     Model runs in realtime and lossy - stores recent
  134.     spikes in a list for realtime learning.
  135.     Uses spike train, with time delay based on distance,        Spikes will trigger absolute refactory period.
  136.     Membrane has simple linear falloff.
  137.  
  138.         notes:
  139.             log(1.0) = 0.0
  140.             log(1.5) = 0.40546510810816438
  141.             log(2.0) = 0.69314718055994529
  142.             log(2.7) = 0.99325177301028345
  143.             log(3.0) = 1.0986122886681098
  144.  
  145.     '''
  146.     def iterate( self ):
  147.         now = float( time.time() )
  148.         self._state_dirty = True; train = self._train
  149.         brane = self._brane; rest = self._rest
  150.         branes = self._branes; temporal = self._temporal
  151.         abs_refactory = self._abs_refactory
  152.         abs_refactory_value = self._abs_refactory_value
  153.         fps = self._fps
  154.         elapsed = now - self._lasttime
  155.         clip = self._clip
  156.         cur = self._lasttime
  157.         last_spike = self._last_spike
  158.         spikers = self._spikers
  159.         thresh = self._thresh
  160.         triggers = self._triggers
  161.  
  162.         ## times of incomming spikes ##
  163.         times = train.keys()
  164.         ## To do, if seziure, lower all connection strengths
  165.         TimSort(times).sort()       # pypy note - list have no .sort(), and JIT dislikes builtin sorted(list)
  166.  
  167.         if not times:
  168.             a = now - self._lasttime
  169.             if a > 0.1: brane = rest
  170.             else:
  171.                 b = a * 10  # 0.0-1.0
  172.                 brane += (rest - brane) * b
  173.             branes.append( (brane,now) )
  174.  
  175.         i = 0
  176.         t = a = b = c = bias = .0
  177.         neuron = self
  178.         ntrain = len(train)
  179.         while train:        #the JIT does only properly support a while loop as the main dispatch loop
  180.             Njitdriver.can_enter_jit(
  181.                 cur=cur, train=train, times=times, branes=branes, last_spike=last_spike, spikers=spikers,
  182.                 temporal=temporal, thresh=thresh, triggers=triggers, self=self,
  183.                 abs_refactory=abs_refactory, abs_refactory_value=abs_refactory_value,
  184.                 i=i, t=t, a=a, b=b, c=c,
  185.                 neuron=neuron, bias=bias
  186.             )
  187.             Njitdriver.jit_merge_point(
  188.                 cur=cur, train=train, times=times, branes=branes, last_spike=last_spike, spikers=spikers,
  189.                 temporal=temporal, thresh=thresh, triggers=triggers, self=self,
  190.                 abs_refactory=abs_refactory, abs_refactory_value=abs_refactory_value,
  191.                 i=i, t=t, a=a, b=b, c=c,
  192.                 neuron=neuron, bias=bias
  193.             )
  194.             ##bias, neuron = train.pop( t ) ## not pypy
  195.             t = times[i]; i += 1
  196.             bias,neuron = train[t]
  197.             del train[t]
  198.  
  199.  
  200.             if t <= cur:
  201.                 #print 'time error'
  202.                 pass
  203.             else:
  204.                 a = t - cur
  205.                 cur += a
  206.                 #print 'delay', a
  207.                 if cur - last_spike < abs_refactory:
  208.                     brane = abs_refactory_value
  209.                     branes.append( (brane,cur) )
  210.                 else:
  211.                     spikers.append( neuron )
  212.                     if a > 0.1:
  213.                         brane = rest + bias
  214.                         branes.append( (brane,cur) )
  215.                     else:
  216.                         b = a * 10  # 0.0-1.0
  217.                         brane += (rest - brane) * b
  218.                         c = b * temporal
  219.                         bias *= math.log( (temporal-c)+2.8 )
  220.                         brane += bias
  221.                         branes.append( (brane,cur) )
  222.  
  223.                         if brane > thresh:
  224.                             triggers.append( neuron )
  225.                             self.spike( cur )
  226.                             brane = abs_refactory_value
  227.                             #fps *= 0.25        # was this to play catch up?
  228.                             break # this is efficient!
  229.  
  230.         #self._train = {}
  231.         self._brane = brane
  232.         #for lst in [branes, spikers, triggers]:    # not allowed in pypy
  233.         while len(branes) > 512: branes.pop(0)      # Adjust this if you run out of memory
  234.         while len(spikers) > clip: spikers.pop(0)
  235.         while len(triggers) > clip: triggers.pop(0)
  236.  
  237.         self._lasttime = end = float(time.time())
  238.         #print ntrain, end-now
  239.  
  240.  
  241.     def detach( self ):
  242.         self._inputs = {}       # time:neuron
  243.         self._outputs = []  # children (neurons)
  244.         self._train = {}
  245.         self._branes = []
  246.         self._spikers = []  # last spikers
  247.         self._triggers = [] # last spikers to cause a spike
  248.  
  249.     def __init__( self, name='neuron', x=.0,y=.0,z=.0, column=0, layer=0, fps=12, thresh=100.0, dendrite_bias=35.0, dendrite_noise=1.0, temporal=1.0, distance_factor=0.1, red=.0, green=.0, blue=.0 ):
  250.         self._name = name
  251.         self._fps = fps     # active fps 10?
  252.         self._thresh = thresh
  253.         self._column = column
  254.         self._layer = layer
  255.         self._brane = self._rest = -65.0
  256.         self._abs_refactory = 0.05
  257.         self._abs_refactory_value = -200.0
  258.         self._spike_value = 200.0
  259.         self._temporal = temporal   # ranges 1.0 - inf
  260.         self._distance_factor = distance_factor
  261.         self._dendrite_bias = dendrite_bias
  262.         self._dendrite_noise = dendrite_noise
  263.         self._clip = 128
  264.         self._learning = False
  265.         self._learning_rate = 0.1
  266.  
  267.         ## the spike train of incomming spikes
  268.         self._train = {}
  269.  
  270.         ## list of tuples, (brane value, abs time)
  271.         ## use this list to render wave timeline ##
  272.         self._branes = []
  273.  
  274.         self._spikers = []  # last spikers
  275.         self._triggers = [] # last spikers to cause a spike
  276.         self._lasttime = time.time()
  277.         self._last_spike = 0
  278.         self._inputs = {}       # time:neuron
  279.         self._outputs = []  # children (neurons)
  280.  
  281.         self._color = [ red, green, blue ]
  282.         #x = uniform( 0.2, 0.8 )
  283.         #y = random()   #uniform( 0.2, 0.8 )
  284.         #z = random()   #uniform( 0.2, 0.8 )
  285.         self._pos = [ x,y,z ]
  286.         self._spike_callback = None
  287.         self._state_dirty = False
  288.         self._active = False
  289.         self._cached_distances = {}
  290.         self._clipped_spikes = 0    # for debugging
  291.  
  292.         self._draw_spike = False
  293.         #self._braneRect = self._spikeRect = None
  294.  
  295.     def randomize( self ):
  296.         for n in self._inputs:
  297.             bias = self._dendrite_bias + uniform( -self._dendrite_noise, self._dendrite_noise )
  298.             self._inputs[ n ] = bias
  299.  
  300.  
  301.     def mutate( self, v ):
  302.         for n in self._spikers:
  303.             self._inputs[ n ] += uniform(-v*2,v*2)
  304.         for n in self._triggers:
  305.             self._inputs[ n ] += uniform(-v,v)
  306.  
  307.         if not self._spikes or not self._triggers:
  308.             for n in self._inputs:
  309.                 self._inputs[ n ] += uniform(-v,v)
  310.  
  311.  
  312.     def reward( self, v ):
  313.         if not self._spikers: print( 'no spikers to reward' )
  314.         for n in self._spikers:
  315.             bias = self._inputs[ n ]
  316.             if abs(bias) < 100:
  317.                 if bias > 15:
  318.                     self._inputs[ n ] += v
  319.                 else:
  320.                     self._inputs[ n ] -= v
  321.            
  322.  
  323.     def punish( self, v ):
  324.         for n in self._inputs:
  325.             self._inputs[n] *= 0.9
  326.            
  327.         for n in self._spikers:
  328.             self._inputs[ n ] += uniform( -v, v )
  329.  
  330.  
  331.  
  332.     def attach_dendrite( self, neuron ):
  333.         bias = self._dendrite_bias + uniform( -self._dendrite_noise, self._dendrite_noise )
  334.         if random()*random() > 0.5: bias = -bias
  335.         # add neuron to input list
  336.         if neuron not in self._inputs:
  337.             self._inputs[ neuron ] = bias
  338.             #print 'attached neuron', neuron, bias
  339.         if self not in neuron._outputs:
  340.             neuron._outputs.append( self )
  341.             neuron.update_distances()
  342.         return bias
  343.  
  344.     def update_distances( self ):
  345.         for child in self._outputs:
  346.             dist = distance( self._pos, child._pos )
  347.             self._cached_distances[ child ] = dist
  348.  
  349.     def spike( self, t ):
  350.         #print 'spike', t
  351.         self._draw_spike = True
  352.         self._last_spike = t
  353.         self._branes.append( (self._spike_value,t) )
  354.         self._brane = self._abs_refactory_value
  355.         self._branes.append( (self._brane,t) )
  356.         if self._learning and self._triggers:
  357.             #print 'learning'
  358.             n = self._triggers[-1]
  359.             bias = self._inputs[ n ]
  360.             if bias > 0: self._inputs[n] += self._learning_rate
  361.             else: self._inputs[n] -= self._learning_rate
  362.  
  363.         if self._spike_callback:
  364.             self._spike_callback( t )
  365.  
  366.         for child in self._outputs:
  367.             #print 'spike to', child
  368.             bias = child._inputs[ self ]
  369.             #dist = distance( self._pos, child._pos )
  370.             dist = self._cached_distances[ child ]
  371.             dist *= self._distance_factor
  372.             child._train[ t+dist ] = (bias,self)
  373.  
  374.     def stop( self ):
  375.         self._active = False
  376.         print( 'clipped spikes', self._clipped_spikes )
  377.     def start( self ):
  378.         self._active = True
  379.         self.iterate()
  380.  
  381.     def setup_draw( self, format, braneRect, groupRect, spikeRect, colors ):
  382.         self._braneRect = braneRect
  383.         self._groupRect = groupRect
  384.         self._spikeRect = spikeRect
  385.         self._sdl_colors = colors
  386.         r,g,b = self._color
  387.         self._group_color = RSDL.MapRGB(format, int(r*255), int(g*255), int(b*255))
  388.  
  389.     def draw( self, surf ):
  390.         #if self._braneRect:
  391.         fmt = surf.c_format
  392.         b = int(self._brane * 6)
  393.         if b > 255: b = 255
  394.         elif b < 0: b = 0
  395.         color = RSDL.MapRGB(fmt, 0, 0, b)
  396.         RSDL.FillRect(surf, self._braneRect, color)
  397.         RSDL.FillRect(surf, self._groupRect, self._group_color)
  398.         if self._draw_spike:
  399.             RSDL.FillRect(surf, self._spikeRect, self._sdl_colors['white'])
  400.         else:
  401.             RSDL.FillRect(surf, self._spikeRect, color )#self._sdl_colors['black'])
  402.         self._draw_spike = False
  403.  
  404.     def dump_model( self, brain ):
  405.         #a = ''
  406.         x,y,z = self._pos
  407.         a = '{ "pos" : (%s, %s, %s,), ' %(x,y,z)        # self._pos  not allowed in pypy, unpack tuple first
  408.         b = ''
  409.         for brane,seconds in self._branes: b += '(%s,%s),' %(brane,seconds)
  410.         a += ' "anim" : ( %s ), ' %b
  411.         b = ''
  412.         for n in self._outputs:
  413.             idx = brain.get_neuron_index( n )
  414.             b += '%s,' %idx
  415.         a += ' "outputs" : ( %s ) }' %b
  416.         return a
  417.  
  418.  
  419.  
  420. class Brain( object ):
  421.     def loop( self ):
  422.         self._active = True
  423.         fmt = self.screen.c_format
  424.         RSDL.FillRect(self.screen, lltype.nullptr(RSDL.Rect), self.ColorGrey)
  425.         layers = self._layers
  426.         neurons = self._neurons
  427.         pulse_layers = self._pulse_layers
  428.         screen = self.screen
  429.         loops = 0  
  430.         now = start = float( time.time() )
  431.         while self._active:
  432.             #Bjitdriver.can_enter_jit( layers=layers, neurons=neurons, pulse_layers=pulse_layers, loops=loops )
  433.             #Bjitdriver.jit_merge_point( layers=layers, neurons=neurons, pulse_layers=pulse_layers, loops=loops)
  434.             now = float( time.time() )
  435.             self._fps = loops / float(now-start)
  436.             for i,lay in enumerate(self._layers):
  437.                 if self._pulse_layers[i] and False:
  438.                     #print 'pulse layer: %s neurons: %s ' %(i, len(lay))
  439.                     for n in lay:
  440.                         if random()*random() > 0.8:
  441.                             n.spike( now )
  442.             for i,col in enumerate(self._columns):
  443.                 if self._pulse_columns[i]:
  444.                     for n in col: n.spike(now)
  445.             for n in self._neurons:
  446.                 n.iterate()
  447.                 n.draw(self.screen)
  448.             #r,w,x = rpoll.select( [self._stdin], [], [], 1 )   # wait
  449.             rl,wl,xl = rpoll.select( [0], [], [], 0.000001 )    # wait
  450.             if rl:
  451.                 cmd = self._stdin.readline().strip('\n').strip(' ')
  452.                 self.do_command( cmd )
  453.             loops += 1
  454.             self._iterations = loops
  455.             #print loops        # can not always print in mainloop, then select can never read from stdin
  456.             RSDL.Flip(self.screen)
  457.             #self._fps = float(time.time()) - now
  458.         #return loops
  459.         return 0
  460.  
  461.     def __init__(self):
  462.         start = float(time.time())
  463.         self._neurons = []
  464.         self._columns = []
  465.         self._layers = [ [] ] * LAYERS
  466.         self._pulse_layers = [0] * LAYERS
  467.         self._pulse_layers[ 0 ] = 1
  468.  
  469.         self._pulse_columns = [0] * COLUMNS
  470.         self._pulse_columns[ 0 ] = 1
  471.         self._pulse_columns[ 1 ] = 1
  472.         self._pulse_columns[ 2 ] = 1
  473.         self._pulse_columns[ 3 ] = 1
  474.  
  475.  
  476.         inc = 360.0 / COLUMNS
  477.         scale = float( LAYERS )
  478.         expansion = 1.333
  479.         linc = scale / LAYERS
  480.         for column in range(COLUMNS):
  481.             colNeurons = []
  482.             self._columns.append( colNeurons )
  483.             X = math.sin( radians(column*inc) )
  484.             Y = math.cos( radians(column*inc) )
  485.             expanding = STEM
  486.             width = 1.0 / scale
  487.             for layer in range(LAYERS):
  488.                 Z = layer * linc
  489.                 r = random() * random()
  490.                 g = 0.2
  491.                 b = 0.2
  492.                 for i in range(int(expanding)):
  493.                     x = uniform( -width, width )
  494.                     rr = random()*random()      # DJ's trick
  495.                     y = uniform( -width*rr, width*rr ) + X
  496.                     z = Z + Y
  497.                     # create 50/50 exitatory/inhibitory
  498.                     n = RecurrentSpikingModel(x=x, y=y, z=z, column=column, layer=layer, red=r, green=g, blue=b )
  499.                     self._neurons.append( n )
  500.                     colNeurons.append( n )
  501.                     self._layers[ layer ].append( n )
  502.  
  503.                 expanding *= expansion
  504.                 width *= expansion
  505.  
  506.         dendrites = 0
  507.         interlayer = 0
  508.         for lay in self._layers:
  509.             for a in lay:
  510.                 for b in lay:
  511.                     if a is not b and a._column == b._column:
  512.                         a.attach_dendrite( b )
  513.                         dendrites += 1
  514.                         interlayer += 1
  515.  
  516.         intercol = 0
  517.         for col in self._columns:
  518.             for a in col:
  519.                 for b in col:
  520.                     if a is not b and random()*random() > 0.75:
  521.                         a.attach_dendrite( b )
  522.                         intercol += 1
  523.                         dendrites += 1
  524.  
  525.         intercore = 0
  526.         core = self._layers[-1]
  527.         for a in core:
  528.             for b in core:
  529.                 if a is not b and random()*random() > 0.85:
  530.                     a.attach_dendrite( b )
  531.                     intercore += 1
  532.                     dendrites += 1
  533.  
  534.         print( 'brain creation time (seconds)', float(time.time())-start )
  535.         print( 'neurons per column', len(self._columns[0]) )
  536.         print( 'inter-layer dendrites', interlayer )
  537.         print( 'inter-column dendrites', intercol )
  538.         print( 'inter-neocoretex dendrites', intercore )
  539.         print( 'total dendrites', dendrites )
  540.         print( 'total neurons', len(self._neurons) )
  541.         for i,lay in enumerate(self._layers):
  542.             print( 'layer: %s   neurons: %s' %(i,len(lay)) )
  543.         for i,col in enumerate(self._columns):
  544.             print( 'column: %s  neurons: %s' %(i,len(col)) )
  545.  
  546.  
  547.  
  548.         self._stdin = streamio.fdopen_as_stream(0, 'r', 1)
  549.         #self._stdout = streamio.fdopen_as_stream(1, 'w', 1)
  550.         #self._stderr = streamio.fdopen_as_stream(2, 'w', 1)
  551.  
  552.         self._width = 640; self._height = 480
  553.         assert RSDL.Init(RSDL.INIT_VIDEO) >= 0
  554.         self.screen = RSDL.SetVideoMode(self._width, self._height, 32, 0)
  555.         assert self.screen
  556.         fmt = self.screen.c_format
  557.         self.ColorWhite = white = RSDL.MapRGB(fmt, 255, 255, 255)
  558.         self.ColorGrey = grey = RSDL.MapRGB(fmt, 128, 128, 128)
  559.         self.ColorBlack = black = RSDL.MapRGB(fmt, 0, 0, 0)
  560.         self.ColorBlue = blue = RSDL.MapRGB(fmt, 0, 0, 200)
  561.  
  562.         colors = {'white':white, 'grey':grey, 'black':black, 'blue':blue}
  563.  
  564.         x = 1; y = 1
  565.         for i,n in enumerate(self._neurons):
  566.             braneRect = RSDL_helper.mallocrect(x, y, 12, 12)
  567.             groupRect = RSDL_helper.mallocrect(x, y, 12, 2)
  568.             spikeRect = RSDL_helper.mallocrect(x+4, y+4, 4, 4)
  569.             n.setup_draw( self.screen.c_format, braneRect, groupRect, spikeRect, colors )
  570.             x += 13
  571.             if x >= self._width-14:
  572.                 x = 1
  573.                 y += 13
  574.  
  575.     def do_command( self, cmd ):
  576.         if cmd == 'spike-all':
  577.             t = float(time.time())
  578.             for n in self._neurons: n.spike(t)
  579.         elif cmd == 'spike-one':
  580.             t = float(time.time())
  581.             self._neurons[0].spike(t)
  582.         elif cmd == 'spike-column':
  583.             t = float(time.time())
  584.             for n in self._columns[0]:
  585.                 n.spike(t)
  586.         elif cmd == 'info':
  587.             info = self.info()
  588.             #sys.stderr.write( info )
  589.             #sys.stderr.flush()
  590.             print( info )
  591.         elif cmd == 'view-model':
  592.             a = ''
  593.             for n in self._neurons: a += n.dump_model( self ) + ','
  594.             print( '<view_model> ( %s )' %a )
  595.  
  596.     def info(self):
  597.         r = ' "num-layers": %s,' %len(self._layers)
  598.         r += ' "num-neurons": %s,' %len(self._neurons)
  599.         r += ' "fps" : %s, ' %self._fps
  600.         r += ' "iterations" : %s, ' %self._iterations
  601.         return '<load_info> { %s }' %r
  602.  
  603.     def get_neuron_index( self, n ): return self._neurons.index( n )
  604.  
  605.  
  606.  
  607.  
  608. import subprocess, select, time
  609. if '--blender' not in sys.argv: import gtk, glib
  610.  
  611. class App:
  612.     def load_info( self, arg ): print( arg )
  613.     def view_model( self, arg ):
  614.         pickle.dump( arg, open('/tmp/brain.data','wb'), -1 )
  615.         os.system( '%s -P rAI.py --blender' %BLENDER_DIR )
  616.  
  617.     def __init__(self):
  618.         self._commands = cmds = []
  619.         self.win = gtk.Window()
  620.         self.win.connect('destroy', lambda w: gtk.main_quit())
  621.         self.root = gtk.VBox(False,10); self.win.add( self.root )
  622.         self.root.set_border_width(20)
  623.         self.header = header = gtk.HBox()
  624.         self.root.pack_start( header, expand=False )
  625.         b = gtk.Button('spike all neurons')
  626.         b.connect('clicked', lambda b,s: s._commands.append('spike-all'), self )
  627.         self.header.pack_start( b, expand=False )
  628.  
  629.         b = gtk.Button('spike one neuron')
  630.         b.connect('clicked', lambda b,s: s._commands.append('spike-one'), self )
  631.         self.header.pack_start( b, expand=False )
  632.  
  633.         b = gtk.Button('spike column 1')
  634.         b.connect('clicked', lambda b,s: s._commands.append('spike-column'), self )
  635.         self.header.pack_start( b, expand=False )
  636.  
  637.         b = gtk.Button('view model')
  638.         b.connect('clicked', lambda b,s: s._commands.append('view-model'), self )
  639.         self.header.pack_start( b, expand=False )
  640.  
  641.         self.header.pack_start( gtk.SeparatorMenuItem() )
  642.  
  643.         b = gtk.Button('debug')
  644.         b.connect('clicked', lambda b,s: s._commands.append('info'), self )
  645.         self.header.pack_start( b, expand=False )
  646.  
  647.         da = gtk.DrawingArea()
  648.         da.set_size_request( 640,480 )
  649.         da.connect('realize', self.realize)
  650.         self.root.pack_start( da )
  651.  
  652.         self._read = None
  653.         glib.timeout_add( 33, self.loop )
  654.         self.win.show_all()
  655.  
  656.  
  657.     def realize(self, da ):
  658.         print( 'gtk drawing area realize' )
  659.         xid = da.window.xid
  660.         self._process = process = subprocess.Popen( 'python rAI.py --pypy --subprocess %s' %xid, stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=32, shell=True )
  661.         self._write = write = process.stdin
  662.         self._read = read = process.stdout
  663.         print( 'read pipe', read )
  664.         print( 'read write', write )
  665.  
  666.     def loop( self ):
  667.         if self._read:
  668.             rlist,wlist,xlist = select.select( [self._read], [], [], 0.001 )
  669.             while self._commands:
  670.                 cmd = self._commands.pop()
  671.                 print( 'sending cmd ->', cmd )
  672.                 self._write.write( '%s\n'%cmd )
  673.                 self._write.flush()
  674.             if rlist:
  675.                 a = self._read.readline().strip()
  676.                 if a:
  677.                     print( a )
  678.                     if a.startswith('<'):
  679.                         func = a[ 1 : a.index('>') ]
  680.                         arg = a[ a.index('>')+1 : ].strip()
  681.                         func = getattr(self, func)
  682.                         func( eval(arg) )
  683.         return True
  684.  
  685. class BlenderExport(object):
  686.     #bpy.ops.anim.change_frame( i )     # can not be used from the command line, invalid context
  687.     #mat.diffuse_color.r = 0.1
  688.     #mat.keyframe_insert('diffuse_color')
  689.  
  690.     def animate_material( self, mat, anim ):
  691.         mat.keyframe_insert('emit')
  692.         start = anim[0][1]
  693.         ecurve = mat.animation_data.action.fcurves[0]
  694.         i = 0
  695.         for brane,seconds in anim:
  696.             t = seconds-start
  697.             t *= 100
  698.             if brane < 99: v = (brane+80) * .01
  699.             else: v = 50
  700.             bez = ecurve.keyframe_points.add( frame=t, value=v )
  701.             i += 1
  702.            
  703.     def create_taper_curve( self, thickness=20.0, steps=3 ):
  704.         # the Y+ defines the tappering
  705.         data = bpy.data.curves.new(name='dendriteTaper', type='CURVE')
  706.         spline = data.splines.new('BEZIER')
  707.         #spline.bezier_points.add()     # new spline always has one bez
  708.         x = .0; y=0.5 * thickness; z = .0
  709.         bez = spline.bezier_points[-1]
  710.         bez.co.x = x; bez.co.y = y; bez.co.z = z
  711.         bez.handle1.x = x + 0.1
  712.         bez.handle1.y = y / 2
  713.         bez.handle1.z = z
  714.         bez.handle2.x = x + 0.1
  715.         bez.handle2.y = y / 2
  716.         bez.handle2.z = z
  717.  
  718.         if 0:
  719.             inc = 1.0 / steps
  720.             x = inc
  721.             for i in range(steps):
  722.                 spline.bezier_points.add()
  723.                 y= (0.1 * thickness) + uniform(.0,0.01)
  724.                 bez = spline.bezier_points[-1]
  725.                 bez.co.x = x; bez.co.y = y; bez.co.z = z
  726.                 bez.handle1.x = x
  727.                 bez.handle1.y = y
  728.                 bez.handle1.z = z
  729.                 bez.handle2.x = x + inc
  730.                 bez.handle2.y = y
  731.                 bez.handle2.z = z
  732.                 x += inc
  733.  
  734.         spline.bezier_points.add()
  735.         x = 1.0; y=0.05 * thickness
  736.         bez = spline.bezier_points[-1]
  737.         bez.co.x = x; bez.co.y = y; bez.co.z = z
  738.         bez.handle1.x = x - 0.5
  739.         bez.handle1.y = y
  740.         bez.handle1.z = z
  741.         bez.handle2.x = x - 0.5
  742.         bez.handle2.y = y
  743.         bez.handle2.z = z
  744.  
  745.         obj = bpy.data.objects.new(name='dendriteTraper', object_data=data)
  746.         bpy.context.scene.objects.link(obj)
  747.         return obj
  748.  
  749.     def __init__(self):
  750.         data = bpy.data.curves.new(name='brain', type='CURVE')
  751.         data.taper_object = self.create_taper_curve()
  752.         self._dendrite_curves = data
  753.         data.dimensions = '3D'
  754.         data.resolution_u = 3
  755.         #print( dir(data) )
  756.         brain = pickle.load( open('/tmp/brain.data','rb') )
  757.         steps = 5
  758.         self._neuron_cell_bodies = ncb = []
  759.         self._neuron_materials = mats = []
  760.         for i,n in enumerate(brain):
  761.             x,y,z = n['pos']
  762.             bpy.ops.mesh.primitive_ico_sphere_add() # does not return mesh
  763.             for ob in bpy.data.objects:
  764.                 if ob.name.startswith('Icosphere') and ob not in ncb:
  765.                     ncb.append( ob )
  766.                     ob.location.x = x
  767.                     ob.location.y = y
  768.                     ob.location.z = z
  769.                     ob.scale.x = ob.scale.y = ob.scale.z = .03
  770.                     ob.selected = True
  771.                     bpy.ops.object.shade_smooth()
  772.                     mat = bpy.data.materials.new('cellbody')
  773.                     mats.append( mat )
  774.                     ob.data.add_material( mat )
  775.                     self.animate_material( mat, n['anim'] )
  776.                     for vert in ob.data.verts:
  777.                         if random() > 0.5:
  778.                             p =  uniform(1.0,1.2)
  779.                             vert.co.x *= p
  780.                             vert.co.y *= p
  781.                             vert.co.z *= p
  782.                     break
  783.             for dendrite in n['outputs']:
  784.  
  785.                 spline = data.splines.new('BEZIER')
  786.                 #spline.bezier_points.add()     # new spline always has one bez
  787.                 bez = spline.bezier_points[-1]
  788.                 bez.co.x = x; bez.co.y = y; bez.co.z = z
  789.                 bez.handle1.x = x
  790.                 bez.handle1.y = y
  791.                 bez.handle1.z = z
  792.                 bez.handle2.x = x + uniform(-.1,.1)
  793.                 bez.handle2.y = y + uniform(-.1,.1)
  794.                 bez.handle2.z = z + uniform(-.1,.1)
  795.                
  796.                 dx,dy,dz = brain[ dendrite ]['pos']
  797.                 inc = 1.0 / steps
  798.                 m = inc
  799.                 a = 0.05
  800.                 for step in range(steps):
  801.                     mx = x + ((dx-x)*uniform(m-a,m+a))
  802.                     my = y + ((dy-y)*uniform(m-a,m+a))
  803.                     mz = z + ((dz-z)*uniform(m-a,m+a))
  804.                     spline.bezier_points.add()
  805.                     bez = spline.bezier_points[-1]
  806.                     bez.co.x = mx; bez.co.y = my; bez.co.z = mz
  807.                     bez.handle1.x = mx + uniform(-.1,.1)
  808.                     bez.handle1.y = my + uniform(-.1,.1)
  809.                     bez.handle1.z = mz + uniform(-.1,.1)
  810.                     bez.handle2.x = mx + uniform(-.1,.1)
  811.                     bez.handle2.y = my + uniform(-.1,.1)
  812.                     bez.handle2.z = mz + uniform(-.1,.1)
  813.                     m += inc
  814.  
  815.                 spline.bezier_points.add()
  816.                 bez = spline.bezier_points[-1]
  817.                 bez.co.x = dx; bez.co.y = dy; bez.co.z = dz
  818.                 bez.handle1.x = dx
  819.                 bez.handle1.y = dy
  820.                 bez.handle1.z = dz
  821.                 bez.handle2.x = dx + uniform(-.1,.1)
  822.                 bez.handle2.y = dy + uniform(-.1,.1)
  823.                 bez.handle2.z = dz + uniform(-.1,.1)
  824.  
  825.  
  826.         obj = bpy.data.objects.new(name='brain', object_data=data)
  827.         bpy.context.scene.objects.link(obj)
  828.  
  829. if '--subprocess' in sys.argv:
  830.     os.putenv('SDL_WINDOWID', sys.argv[-1])
  831.     def pypy_entry_point():
  832.         #def jitpolicy(*args):
  833.         #   from pypy.jit.metainterp.policy import JitPolicy
  834.         #   return JitPolicy()
  835.  
  836.         brain = Brain()
  837.         brain.loop()
  838.     if '--pypy' in sys.argv:
  839.         from pypy.translator.interactive import Translation
  840.         t = Translation( pypy_entry_point )
  841.         ## NotImplementedError: --gcrootfinder=asmgcc requires standalone ##
  842.         #t.config.translation.suggest(jit=True, jit_debug='steps', jit_backend='x86', gc='boehm')
  843.         t.annotate()
  844.         t.rtype()
  845.         f = t.compile_c()
  846.         f()
  847.     else:
  848.         pypy_entry_point()
  849.  
  850. else:
  851.     if '--blender' in sys.argv:
  852.         import bpy
  853.         BlenderExport()
  854.  
  855.     else:
  856.         a = App()
  857.         gtk.main()
  858.         print( '-------------------exit toplevel-----------------' )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement